raspbootin.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /* Copyright (C) 2013 by John Cronin <jncronin@tysos.org>
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. * The above copyright notice and this permission notice shall be included in
  10. * all copies or substantial portions of the Software.
  11. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. * THE SOFTWARE.
  18. */
  19. /* This is a file system based upon the raspbootin bootloader by mrvn:
  20. https://github.com/mrvn/raspbootin
  21. It is a protocol which supports transfer of a kernel over a serial link.
  22. It supports two versions of the protocol, the first defined as per the
  23. above link and a version two which is defined here.
  24. All commands are initiated by the client, and responses are returned
  25. by the server.
  26. Definitions:
  27. <byte> A single byte
  28. <lsb16> A 16-bit number transmitted in LSB format
  29. <lsb32> A 32-bit number transmitted in LSB format
  30. <msb32> A 32-bit number transmitted in MSB format
  31. <string> A string transmitted in the format:
  32. <lsb16 length><byte 0><byte 1>...<byte n>
  33. Note not null-terminated and string is in UTF-8 format
  34. <magic> The four bytes <byte 0x31><byte 0x41><byte 0x59><byte 0x27>
  35. <msg_length> The length of the response sent as a <lsb32> - this is
  36. the length minus the length of <magic> and <crc>
  37. <crc> A CRC-32 checksum of the command or response transmitted as
  38. a <msb32>. If this fails the command should be re-sent.
  39. The particular CRC polynomial is 0x04C11DB7 as per
  40. IEEE 802.3
  41. <dir_entry> A directory entry in the form:
  42. <lsb32 byte_size><lsb32 user_id><lsb32 group_id>
  43. <lsb32 properties><string name>
  44. properties is a bit-mask of file/directory properties
  45. as defined later.
  46. Commands:
  47. All commands take the form: <byte \003><byte \003><byte cmd_id><options>
  48. Compatibility:
  49. RBTIN_V1 Required for raspbootin v1
  50. RBTIN_V2_REQ Required for raspbootin v2
  51. RBTIN_V2_SPEC Optional for raspbootin v2 (support is defined
  52. in the response to cmd_id 0)
  53. Error codes:
  54. 0 Success (returned in error response to cmd_id 1 if
  55. there are no entries within the directory)
  56. -1 Path not found
  57. -2 EOF
  58. -3 CRC error in request
  59. File/directory properties:
  60. These are defined as per the st_mode field in the man page to lstat(2).
  61. In particular, S_IFDIR = 0x40000 is set if the entry is a directory.
  62. Command list:
  63. cmd_id Compatibility Function
  64. 0 RBTIN_V2_REQ ID and query functionality
  65. <options> is <crc>
  66. Returns <magic><msg_length><lsb32 error_code>
  67. <lsb32 functions><crc> if the server is a valid v2
  68. server.
  69. Functions is a bit-mask specifying support for each
  70. function number (1 to support). For example, if a
  71. server supports functions 0-4 inclusive, this will
  72. be 11111b = 0x1f.
  73. 1 RBTIN_V2_SPEC Read directory entries
  74. <options> is <string dir_name><crc>
  75. Returns the entries within the specified directory
  76. Returns:
  77. <magic><msg_length><lsb32 error_code><lsb32 0>
  78. <crc>
  79. - if no entries or error
  80. <magic><msg_length><lsb32 0><lsb32 entry_count>
  81. <byte 0><dir_entry 0><dir_entry 1>...
  82. <dir_entry n><crc>
  83. - if success return a list of the entries
  84. - the <byte 0> defines the dir_entry
  85. version and can be changed in future
  86. versions.
  87. 2 RBTIN_V2_SPEC Read part of a file
  88. <options> is <string file_name><lsb32 start>
  89. <lsb32 length><crc>
  90. Reads the part of a file starting at address start
  91. and of length 'length'
  92. Returns:
  93. <magic><msg_length><lsb32 error_code><lsb32 0>
  94. <crc>
  95. - if error
  96. <magic><msg_length><lsb32 0><lsb32 bytes_read>
  97. <byte 0><byte 1>...<byte n><crc>
  98. - if success
  99. 3 RBTIN_V1 Send the default kernel (all of it)
  100. <options> is empty
  101. Returns:
  102. <lsb32 length><byte 0><byte 1>...<byte n>
  103. 4 RBTIN_V2_SPEC Display a string on the server console
  104. <options> is <string message><crc>
  105. Returns:
  106. <magic><msg_length><lsb32 error_code><crc>
  107. */
  108. /* Specifics of the rpi_boot implementation:
  109. During init, we try and communicate with the server by sending cmd_id 0.
  110. If a valid response is returned we cache the result and continue.
  111. If not, we still assume a server is present but that it is v1 (and
  112. cache supported functionality as 0x8 - only cmd_id 3 supported).
  113. During directory enumeration/file loading, if a v2 response is cached
  114. we use that to try and load the file via the v2 functions.
  115. If v1, and the root directory is enumerated, we return a single member:
  116. /raspbootin of type file and unknown length
  117. If v1, and a directory other than the root directory is enumerated, we
  118. return error code ENOENT
  119. If v1, and the file /raspbootin is requested, we send cmd_id 3 and save
  120. the appropriate section to the buffer (and discard the rest)
  121. If v1, and any other file is requested, we return error code ENOENT
  122. */
  123. #ifndef ENABLE_SERIAL
  124. #error Raspbootin support requires ENABLE_SERIAL in config.h
  125. #endif
  126. #include <string.h>
  127. #include "fs.h"
  128. #include "output.h"
  129. #include "uart.h"
  130. #include "crc32.h"
  131. #include "block.h"
  132. #include "raspbootin.h"
  133. #define UART_TIMEOUT 10000
  134. #define READDIR_BUF_LEN 0x1000
  135. #define MAX_RETRIES 3
  136. #define CLIENT_CAPABILITIES 0x1f
  137. #define BYTE(num, idx) (((num) >> ((idx) * 8)) & 0xff)
  138. #ifdef RASPBOOTIN_DEBUG
  139. #define CHECK(resp, floc) if((resp) == -1) { ret = TIMEOUT; fail_loc = floc; goto cleanup; }
  140. #else
  141. #define CHECK(resp, floc) if((resp) == -1) { ret = TIMEOUT; goto cleanup; }
  142. #endif
  143. static uint32_t server_capabilities = 9; // assume server can interpret
  144. // cmds 0 and 3
  145. static uint32_t client_capabilities = CLIENT_CAPABILITIES;
  146. static char raspbootin_name[] = "raspbootin";
  147. static struct dirent *raspbootin_read_directory(struct fs *fs, char **name);
  148. static FILE *raspbootin_fopen(struct fs *fs, struct dirent *path, const char *mode);
  149. static size_t raspbootin_fread(struct fs *fs, void *ptr, size_t size, size_t nmemb, FILE *stream);
  150. static int raspbootin_fclose(struct fs *fs, FILE *fp);
  151. static int send_message(int cmd_id, void *send_buf, size_t send_buf_len,
  152. void *recv_buf, size_t recv_buf_len);
  153. static int read_lsb32(uint32_t *val, useconds_t timeout)
  154. {
  155. uint32_t ret = 0;
  156. for(int i = 0; i < 4; i++)
  157. {
  158. int rbuf = uart_getc_timeout(timeout);
  159. if(rbuf == -1)
  160. return -1;
  161. uint32_t v = (uint32_t)rbuf & 0xff;
  162. ret |= (v << (i * 8));
  163. }
  164. *val = ret;
  165. return 0;
  166. }
  167. static int send_message_int(int cmd_id, void *send_buf, size_t send_buf_len,
  168. void *recv_buf, size_t recv_buf_len)
  169. {
  170. // Send a message (v2 messages only)
  171. #ifdef RASPBOOTIN_DEBUG
  172. printf("RASPBOOTIN: sending cmd %i\n");
  173. int fail_loc = 0;
  174. #endif
  175. // Check capabilities
  176. if((cmd_id < 0) || (cmd_id > 31))
  177. {
  178. printf("RASPBOOTIN: invalid cmd number %i\n");
  179. return INVALID_CMD;
  180. }
  181. if(cmd_id == 3)
  182. {
  183. printf("RASPBOOTIN: cannot use send_message_int to send cmd 3\n");
  184. return INVALID_CMD;
  185. }
  186. uint32_t msg_capabilities = (1 << cmd_id);
  187. if(!(client_capabilities & msg_capabilities))
  188. {
  189. printf("RASPBOOTIN: client does not support cmd %i\n");
  190. return UNSUPPORTED_CMD;
  191. }
  192. if(!(server_capabilities & msg_capabilities))
  193. {
  194. printf("RASPBOOTIN: server does not support cmd %i\n");
  195. return UNSUPPORTED_CMD;
  196. }
  197. // The crc of the request is calculated from 'options'
  198. uint32_t crc = crc32(send_buf, send_buf_len);
  199. // Disable debug output on the uart
  200. rpi_boot_output_state ostate = output_get_state();
  201. output_disable_uart();
  202. // Clear the receive buffer
  203. while(uart_getc_timeout(1000) != -1);
  204. // Send the message
  205. uart_putc('\003');
  206. uart_putc('\003');
  207. uart_putc(cmd_id);
  208. uint8_t *send_p = (uint8_t *)send_buf;
  209. while(send_buf_len--)
  210. uart_putc(*send_p++);
  211. uart_putc(BYTE(crc, 0));
  212. uart_putc(BYTE(crc, 1));
  213. uart_putc(BYTE(crc, 2));
  214. uart_putc(BYTE(crc, 3));
  215. // Wait for the response
  216. usleep(2000);
  217. // Begin reading response
  218. int r_buf = 0;
  219. int ret = 0;
  220. // Read magic number
  221. uint32_t magic = 0;
  222. CHECK(read_lsb32(&magic, UART_TIMEOUT), 0);
  223. if(magic != MAGIC)
  224. {
  225. #ifdef RASPBOOTIN_DEBUG
  226. printf("RASPBOOTIN: invalid magic received: %08x (expecting %08x)\n", magic, MAGIC);
  227. #endif
  228. ret = INVALID_MAGIC;
  229. goto cleanup;
  230. }
  231. // Read response length
  232. uint32_t resp_length = 0;
  233. CHECK(read_lsb32(&resp_length, UART_TIMEOUT), 1);
  234. // Read error_code
  235. uint32_t error_code = 0;
  236. CHECK(read_lsb32(&error_code, UART_TIMEOUT), 2);
  237. if(error_code != SUCCESS)
  238. {
  239. ret = error_code;
  240. #ifdef RASPBOOTIN_DEBUG
  241. fail_loc = 3;
  242. #endif
  243. goto cleanup;
  244. }
  245. // Read the data (maximum is whatever is greater - recv_buf_len
  246. // or resp_length)
  247. // Resp_length is length of the message minus magic and crc
  248. // therefore it includes the length of resp_length and error_code
  249. // which have already been read, therefore subtract 8
  250. size_t data_to_read_to_buffer = (size_t)(resp_length - 8);
  251. size_t data_to_discard = 0;
  252. size_t data_to_pad = 0;
  253. if(data_to_read_to_buffer > recv_buf_len)
  254. {
  255. data_to_read_to_buffer = recv_buf_len;
  256. data_to_discard = data_to_read_to_buffer - recv_buf_len;
  257. }
  258. else if(recv_buf_len > data_to_read_to_buffer)
  259. data_to_pad = recv_buf_len - data_to_read_to_buffer;
  260. crc = crc32_start();
  261. crc = crc32_append(crc, &magic, 4);
  262. crc = crc32_append(crc, &resp_length, 4);
  263. crc = crc32_append(crc, &error_code, 4);
  264. int data_read = 0;
  265. uint8_t *rptr = (uint8_t *)recv_buf;
  266. while(data_to_read_to_buffer--)
  267. {
  268. r_buf = uart_getc_timeout(UART_TIMEOUT);
  269. CHECK(r_buf, 4);
  270. crc = crc32_append(crc, &r_buf, 1);
  271. *rptr++ = r_buf;
  272. data_read++;
  273. }
  274. while(data_to_discard--)
  275. {
  276. r_buf = uart_getc_timeout(UART_TIMEOUT);
  277. CHECK(r_buf, 5);
  278. crc = crc32_append(crc, &r_buf, 1);
  279. }
  280. while(data_to_pad--)
  281. *rptr++ = 0;
  282. crc = crc32_finish(crc);
  283. // Read the response CRC
  284. uint32_t resp_crc = 0;
  285. CHECK(read_lsb32(&resp_crc, UART_TIMEOUT), 6);
  286. if(resp_crc != crc)
  287. {
  288. ret = CRC_ERROR;
  289. #ifdef RASPBOOTIN_DEBUG
  290. fail_loc = 7;
  291. #endif
  292. goto cleanup;
  293. }
  294. cleanup:
  295. if(ret == 0)
  296. ret = data_read;
  297. // Clear the uart buffer
  298. while(uart_getc_timeout(1000) != -1);
  299. // Re-enable uart debug output
  300. output_restore_state(ostate);
  301. #ifdef RASPBOOTIN_DEBUG
  302. printf("RASPBOOTIN: send_message_int, returning %i (fail_loc %i)\n",
  303. ret, fail_loc);
  304. if(ret == CRC_ERROR)
  305. {
  306. printf("RASPBOOTIN: CRC error: read CRC %08x, expected %08x, magic %08x, resp_length %08x, error_code %08x\n",
  307. resp_crc, crc, magic, resp_length, error_code);
  308. }
  309. #endif
  310. return ret;
  311. }
  312. static int send_message(int cmd_id, void *send_buf, size_t send_buf_len,
  313. void *recv_buf, size_t recv_buf_len)
  314. {
  315. // Send a message, retry on CRC failure
  316. int retries = 0;
  317. while(retries < MAX_RETRIES)
  318. {
  319. int ret = send_message_int(cmd_id, send_buf, send_buf_len,
  320. recv_buf, recv_buf_len);
  321. if(ret >= 0)
  322. return ret;
  323. if(ret != CRC_ERROR)
  324. return ret;
  325. retries++;
  326. }
  327. return CRC_ERROR;
  328. }
  329. int raspbootin_init(struct fs **fs)
  330. {
  331. // Try and communicate with a raspbootin server
  332. uint32_t caps;
  333. int ret = send_message(0, 0, 0, &caps, sizeof(uint32_t));
  334. if(ret == sizeof(uint32_t))
  335. {
  336. printf("RASPBOOTIN: server contacted.\n");
  337. server_capabilities = caps;
  338. #ifdef RASPBOOTIN_DEBUG
  339. printf("RASPBOOTIN: server capabilities: %08x\n", caps);
  340. #endif
  341. }
  342. else
  343. {
  344. #ifdef RASPBOOTIN_DEBUG
  345. printf("RASPBOOTIN: no server response to cmd 0 (ret %i)\n", ret);
  346. #endif
  347. server_capabilities = (1 << 3); // only support v1
  348. }
  349. // Build a block device structure
  350. struct block_device *b_dev = (struct block_device *)malloc(sizeof(struct block_device));
  351. memset(b_dev, 0, sizeof(struct block_device));
  352. b_dev->device_name = raspbootin_name;
  353. // Build a fs structure
  354. struct fs *r_fs = (struct fs *)malloc(sizeof(struct fs));
  355. memset(r_fs, 0, sizeof(struct fs));
  356. r_fs->parent = b_dev;
  357. r_fs->fs_name = raspbootin_name;
  358. r_fs->fopen = raspbootin_fopen;
  359. r_fs->fread = raspbootin_fread;
  360. r_fs->fclose = raspbootin_fclose;
  361. r_fs->read_directory = raspbootin_read_directory;
  362. *fs = r_fs;
  363. return 0;
  364. }
  365. static struct dirent *raspbootin_read_directory(struct fs *fs, char **name)
  366. {
  367. (void)fs;
  368. // Join together the directory name
  369. int dir_name_length = 0;
  370. char **name_p = name;
  371. while(*name_p)
  372. {
  373. dir_name_length += strlen(*name_p);
  374. dir_name_length++;
  375. name_p++;
  376. }
  377. dir_name_length++;
  378. char *dir_name = (char *)malloc(dir_name_length);
  379. name_p = name;
  380. char *dir_name_p = dir_name;
  381. while(*name_p)
  382. {
  383. strcpy(dir_name_p, *name_p);
  384. dir_name_p += strlen(*name_p);
  385. *dir_name_p++ = '/';
  386. name_p++;
  387. }
  388. *dir_name_p = '\0';
  389. // Resolve the root directory to an empty string
  390. int is_root = 0;
  391. if(strcmp(dir_name, "/"))
  392. {
  393. dir_name[0] = '\0';
  394. is_root = 1;
  395. }
  396. // Create a string object of the correct size
  397. // Send a request for the contents of this directory
  398. if(server_capabilities & (1 << 1))
  399. {
  400. uint8_t *buf = (uint8_t *)malloc(READDIR_BUF_LEN);
  401. int ret = send_message(1, dir_name, strlen(dir_name),
  402. buf, READDIR_BUF_LEN);
  403. (void)ret;
  404. }
  405. (void)is_root;
  406. return (void *)0;
  407. }
  408. static FILE *raspbootin_fopen(struct fs *fs, struct dirent *path,
  409. const char *mode)
  410. {
  411. (void)fs;
  412. (void)path;
  413. (void)mode;
  414. return (void *)0;
  415. }
  416. static int raspbootin_fclose(struct fs *fs, FILE *fp)
  417. {
  418. (void)fs;
  419. (void)fp;
  420. return 0;
  421. }
  422. static size_t raspbootin_fread(struct fs *fs, void *ptr, size_t size,
  423. size_t nmemb, FILE *stream)
  424. {
  425. (void)fs;
  426. (void)ptr;
  427. (void)size;
  428. (void)nmemb;
  429. (void)stream;
  430. return 0;
  431. }