aboot.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (c) 2009, Google Inc.
  3. * All rights reserved.
  4. *
  5. * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of The Linux Foundation nor
  15. * the names of its contributors may be used to endorse or promote
  16. * products derived from this software without specific prior written
  17. * permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  26. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * NOTE:
  32. * Although it is very similar, this license text is not identical
  33. * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
  34. */
  35. void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
  36. {
  37. unsigned int chunk;
  38. unsigned int chunk_data_sz;
  39. uint32_t *fill_buf = NULL;
  40. uint32_t fill_val;
  41. uint32_t chunk_blk_cnt = 0;
  42. sparse_header_t *sparse_header;
  43. chunk_header_t *chunk_header;
  44. uint32_t total_blocks = 0;
  45. unsigned long long ptn = 0;
  46. unsigned long long size = 0;
  47. int index = INVALID_PTN;
  48. int i;
  49. uint8_t lun = 0;
  50. index = partition_get_index(arg);
  51. ptn = partition_get_offset(index);
  52. if(ptn == 0) {
  53. fastboot_fail("partition table doesn't exist");
  54. return;
  55. }
  56. size = partition_get_size(index);
  57. if (ROUND_TO_PAGE(sz,511) > size) {
  58. fastboot_fail("size too large");
  59. return;
  60. }
  61. lun = partition_get_lun(index);
  62. mmc_set_lun(lun);
  63. /* Read and skip over sparse image header */
  64. sparse_header = (sparse_header_t *) data;
  65. if ((sparse_header->total_blks * sparse_header->blk_sz) > size) {
  66. fastboot_fail("size too large");
  67. return;
  68. }
  69. data += sparse_header->file_hdr_sz;
  70. if (sparse_header->file_hdr_sz > sizeof(sparse_header_t))
  71. {
  72. /*
  73. * Skip the remaining bytes in a header that is longer than
  74. * we expected.
  75. */
  76. data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
  77. }
  78. debug("=== Sparse Image Header ===\n");
  79. debug("magic: 0x%x\n", sparse_header->magic);
  80. debug("major_version: 0x%x\n", sparse_header->major_version);
  81. debug("minor_version: 0x%x\n", sparse_header->minor_version);
  82. debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
  83. debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
  84. debug("blk_sz: %d\n", sparse_header->blk_sz);
  85. debug("total_blks: %d\n", sparse_header->total_blks);
  86. debug("total_chunks: %d\n", sparse_header->total_chunks);
  87. /* Start processing chunks */
  88. for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
  89. {
  90. /* Read and skip over chunk header */
  91. chunk_header = (chunk_header_t *) data;
  92. data += sizeof(chunk_header_t);
  93. debug("=== Chunk Header ===\n");
  94. debug("chunk_type: 0x%x\n", chunk_header->chunk_type);
  95. debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
  96. debug("total_size: 0x%x\n", chunk_header->total_sz);
  97. if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
  98. {
  99. /*
  100. * Skip the remaining bytes in a header that is longer
  101. * than we expected.
  102. */
  103. data += (sparse_header->chunk_hdr_sz -
  104. sizeof(chunk_header_t));
  105. }
  106. chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
  107. switch (chunk_header->chunk_type)
  108. {
  109. case CHUNK_TYPE_RAW:
  110. if (chunk_header->total_sz !=
  111. (sparse_header->chunk_hdr_sz + chunk_data_sz))
  112. {
  113. fastboot_fail(
  114. "Bogus chunk size for chunk type Raw");
  115. return;
  116. }
  117. if (mmc_write(ptn +
  118. ((uint64_t)total_blocks *
  119. sparse_header->blk_sz),
  120. chunk_data_sz, (unsigned int *)data))
  121. {
  122. fastboot_fail("flash write failure");
  123. return;
  124. }
  125. total_blocks += chunk_header->chunk_sz;
  126. data += chunk_data_sz;
  127. break;
  128. case CHUNK_TYPE_FILL:
  129. if (chunk_header->total_sz !=
  130. (sparse_header->chunk_hdr_sz + sizeof(uint32_t)))
  131. {
  132. fastboot_fail(
  133. "Bogus chunk size for chunk type FILL");
  134. return;
  135. }
  136. fill_buf = (uint32_t *)
  137. memalign(CACHE_LINE,
  138. ROUNDUP(sparse_header->blk_sz,
  139. CACHE_LINE));
  140. if (!fill_buf)
  141. {
  142. fastboot_fail(
  143. "Malloc failed for: CHUNK_TYPE_FILL");
  144. return;
  145. }
  146. fill_val = *(uint32_t *)data;
  147. data = (char *) data + sizeof(uint32_t);
  148. chunk_blk_cnt = chunk_data_sz / sparse_header->blk_sz;
  149. for (i = 0; i < (sparse_header->blk_sz / sizeof(fill_val)); i++)
  150. {
  151. fill_buf[i] = fill_val;
  152. }
  153. for (i = 0; i < chunk_blk_cnt; i++)
  154. {
  155. if (mmc_write(ptn +
  156. ((uint64_t)total_blocks *
  157. sparse_header->blk_sz),
  158. sparse_header->blk_sz, fill_buf))
  159. {
  160. fastboot_fail("flash write failure");
  161. free(fill_buf);
  162. return;
  163. }
  164. total_blocks++;
  165. }
  166. free(fill_buf);
  167. break;
  168. case CHUNK_TYPE_DONT_CARE:
  169. total_blocks += chunk_header->chunk_sz;
  170. break;
  171. case CHUNK_TYPE_CRC:
  172. if (chunk_header->total_sz !=
  173. sparse_header->chunk_hdr_sz)
  174. {
  175. fastboot_fail(
  176. "Bogus chunk size for chunk type Dont Care");
  177. return;
  178. }
  179. total_blocks += chunk_header->chunk_sz;
  180. data += chunk_data_sz;
  181. break;
  182. default:
  183. debug("Unkown chunk type: %x\n",
  184. chunk_header->chunk_type);
  185. fastboot_fail("Unknown chunk type");
  186. return;
  187. }
  188. }
  189. debug("Wrote %d blocks, expected to write %d blocks\n",
  190. total_blocks, sparse_header->total_blks);
  191. if (total_blocks != sparse_header->total_blks)
  192. fastboot_fail("sparse image write failure");
  193. fastboot_okay("");
  194. return;
  195. }