GoogleGit

blob: 10a84c1241005e1b66f2501435a81d42c2353930 [file] [log] [blame]
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  18. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  19. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  21. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  22. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  23. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  24. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  25. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. #define min(a, b) \
  29. ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
  30. #define round_down(a, b) \
  31. ({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); })
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <sparse/sparse.h>
  37. #include "fastboot.h"
  38. static char ERROR[128];
  39. char *fb_get_error(void)
  40. {
  41. return ERROR;
  42. }
  43. static int check_response(usb_handle *usb, unsigned int size, char *response)
  44. {
  45. unsigned char status[65];
  46. int r;
  47. for(;;) {
  48. r = usb_read(usb, status, 64);
  49. if(r < 0) {
  50. sprintf(ERROR, "status read failed (%s)", strerror(errno));
  51. usb_close(usb);
  52. return -1;
  53. }
  54. status[r] = 0;
  55. if(r < 4) {
  56. sprintf(ERROR, "status malformed (%d bytes)", r);
  57. usb_close(usb);
  58. return -1;
  59. }
  60. if(!memcmp(status, "INFO", 4)) {
  61. fprintf(stderr,"(bootloader) %s\n", status + 4);
  62. continue;
  63. }
  64. if(!memcmp(status, "OKAY", 4)) {
  65. if(response) {
  66. strcpy(response, (char*) status + 4);
  67. }
  68. return 0;
  69. }
  70. if(!memcmp(status, "FAIL", 4)) {
  71. if(r > 4) {
  72. sprintf(ERROR, "remote: %s", status + 4);
  73. } else {
  74. strcpy(ERROR, "remote failure");
  75. }
  76. return -1;
  77. }
  78. if(!memcmp(status, "DATA", 4) && size > 0){
  79. unsigned dsize = strtoul((char*) status + 4, 0, 16);
  80. if(dsize > size) {
  81. strcpy(ERROR, "data size too large");
  82. usb_close(usb);
  83. return -1;
  84. }
  85. return dsize;
  86. }
  87. strcpy(ERROR,"unknown status code");
  88. usb_close(usb);
  89. break;
  90. }
  91. return -1;
  92. }
  93. static int _command_start(usb_handle *usb, const char *cmd, unsigned size,
  94. char *response)
  95. {
  96. int cmdsize = strlen(cmd);
  97. if(response) {
  98. response[0] = 0;
  99. }
  100. if(cmdsize > 64) {
  101. sprintf(ERROR,"command too large");
  102. return -1;
  103. }
  104. if(usb_write(usb, cmd, cmdsize) != cmdsize) {
  105. sprintf(ERROR,"command write failed (%s)", strerror(errno));
  106. usb_close(usb);
  107. return -1;
  108. }
  109. return check_response(usb, size, response);
  110. }
  111. static int _command_data(usb_handle *usb, const void *data, unsigned size)
  112. {
  113. int r;
  114. r = usb_write(usb, data, size);
  115. if(r < 0) {
  116. sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
  117. usb_close(usb);
  118. return -1;
  119. }
  120. if(r != ((int) size)) {
  121. sprintf(ERROR, "data transfer failure (short transfer)");
  122. usb_close(usb);
  123. return -1;
  124. }
  125. return r;
  126. }
  127. static int _command_end(usb_handle *usb)
  128. {
  129. int r;
  130. r = check_response(usb, 0, 0);
  131. if(r < 0) {
  132. return -1;
  133. }
  134. return 0;
  135. }
  136. static int _command_send(usb_handle *usb, const char *cmd,
  137. const void *data, unsigned size,
  138. char *response)
  139. {
  140. int r;
  141. if (size == 0) {
  142. return -1;
  143. }
  144. r = _command_start(usb, cmd, size, response);
  145. if (r < 0) {
  146. return -1;
  147. }
  148. r = _command_data(usb, data, size);
  149. if (r < 0) {
  150. return -1;
  151. }
  152. r = _command_end(usb);
  153. if(r < 0) {
  154. return -1;
  155. }
  156. return size;
  157. }
  158. static int _command_send_no_data(usb_handle *usb, const char *cmd,
  159. char *response)
  160. {
  161. return _command_start(usb, cmd, 0, response);
  162. }
  163. int fb_command(usb_handle *usb, const char *cmd)
  164. {
  165. return _command_send_no_data(usb, cmd, 0);
  166. }
  167. int fb_command_response(usb_handle *usb, const char *cmd, char *response)
  168. {
  169. return _command_send_no_data(usb, cmd, response);
  170. }
  171. int fb_download_data(usb_handle *usb, const void *data, unsigned size)
  172. {
  173. char cmd[64];
  174. int r;
  175. sprintf(cmd, "download:%08x", size);
  176. r = _command_send(usb, cmd, data, size, 0);
  177. if(r < 0) {
  178. return -1;
  179. } else {
  180. return 0;
  181. }
  182. }
  183. #define USB_BUF_SIZE 1024
  184. static char usb_buf[USB_BUF_SIZE];
  185. static int usb_buf_len;
  186. static int fb_download_data_sparse_write(void *priv, const void *data, int len)
  187. {
  188. int r;
  189. usb_handle *usb = priv;
  190. int to_write;
  191. const char *ptr = data;
  192. if (usb_buf_len) {
  193. to_write = min(USB_BUF_SIZE - usb_buf_len, len);
  194. memcpy(usb_buf + usb_buf_len, ptr, to_write);
  195. usb_buf_len += to_write;
  196. ptr += to_write;
  197. len -= to_write;
  198. }
  199. if (usb_buf_len == USB_BUF_SIZE) {
  200. r = _command_data(usb, usb_buf, USB_BUF_SIZE);
  201. if (r != USB_BUF_SIZE) {
  202. return -1;
  203. }
  204. usb_buf_len = 0;
  205. }
  206. if (len > USB_BUF_SIZE) {
  207. if (usb_buf_len > 0) {
  208. sprintf(ERROR, "internal error: usb_buf not empty\n");
  209. return -1;
  210. }
  211. to_write = round_down(len, USB_BUF_SIZE);
  212. r = _command_data(usb, ptr, to_write);
  213. if (r != to_write) {
  214. return -1;
  215. }
  216. ptr += to_write;
  217. len -= to_write;
  218. }
  219. if (len > 0) {
  220. if (len > USB_BUF_SIZE) {
  221. sprintf(ERROR, "internal error: too much left for usb_buf\n");
  222. return -1;
  223. }
  224. memcpy(usb_buf, ptr, len);
  225. usb_buf_len = len;
  226. }
  227. return 0;
  228. }
  229. static int fb_download_data_sparse_flush(usb_handle *usb)
  230. {
  231. int r;
  232. if (usb_buf_len > 0) {
  233. r = _command_data(usb, usb_buf, usb_buf_len);
  234. if (r != usb_buf_len) {
  235. return -1;
  236. }
  237. usb_buf_len = 0;
  238. }
  239. return 0;
  240. }
  241. int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s)
  242. {
  243. char cmd[64];
  244. int r;
  245. int size = sparse_file_len(s, true, false);
  246. if (size <= 0) {
  247. return -1;
  248. }
  249. sprintf(cmd, "download:%08x", size);
  250. r = _command_start(usb, cmd, size, 0);
  251. if (r < 0) {
  252. return -1;
  253. }
  254. r = sparse_file_callback(s, true, false, fb_download_data_sparse_write, usb);
  255. if (r < 0) {
  256. return -1;
  257. }
  258. fb_download_data_sparse_flush(usb);
  259. return _command_end(usb);
  260. }