Advertisement
Guest User

Untitled

a guest
Jan 27th, 2020
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.10 KB | None | 0 0
  1. /*
  2. * RouterBoot helper routines
  3. *
  4. * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
  5. * Copyright (C) 2018 Chris Schimp <silverchris@gmail.com>
  6. * Copyright (C) 2019 Robert Marko <robimarko@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License version 2 as published
  10. * by the Free Software Foundation.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <stddef.h>
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include <sys/types.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <endian.h>
  21. #include <arpa/inet.h>
  22.  
  23. #include <lzo/lzo1x.h>
  24.  
  25. #include "rle.h"
  26. #include "routerboot.h"
  27.  
  28. inline uint32_t
  29. get_u32(const void *buf)
  30. {
  31. #if __BYTE_ORDER == __LITTLE_ENDIAN
  32. return *(uint32_t *)buf;
  33. #elif __BYTE_ORDER == __BIG_ENDIAN
  34. const uint8_t *p = buf;
  35. return ((uint32_t) p[3] + ((uint32_t) p[2] << 8) +
  36. ((uint32_t) p[1] << 16) + ((uint32_t) p[0] << 24));
  37. #else
  38. #error "Unknown byte order!"
  39. #endif
  40. }
  41.  
  42. int
  43. routerboot_find_tag(uint8_t *buf, unsigned int buflen, uint16_t tag_id,
  44. uint8_t **tag_data, uint16_t *tag_len)
  45. {
  46. uint16_t id;
  47. uint16_t len;
  48. uint32_t magic;
  49. bool align = false;
  50. int ret;
  51.  
  52. if (buflen < 4)
  53. return 1;
  54.  
  55. magic = get_u32(buf);
  56.  
  57. switch (magic) {
  58. case RB_MAGIC_LZOR:
  59. buf += 4;
  60. buflen -= 4;
  61. break;
  62. case RB_MAGIC_ERD:
  63. align = true;
  64. /* fall trough */
  65. case RB_MAGIC_HARD:
  66. /* skip magic value */
  67. buf += 4;
  68. buflen -= 4;
  69. break;
  70.  
  71. case RB_MAGIC_SOFT:
  72. if (buflen < 8)
  73. return 1;
  74.  
  75. /* skip magic and CRC value */
  76. buf += 8;
  77. buflen -= 8;
  78.  
  79. break;
  80.  
  81. default:
  82. return 1;
  83. }
  84.  
  85. ret = 1;
  86. while (buflen > 4){
  87. uint32_t id_and_len = get_u32(buf);
  88. buf += 4;
  89. buflen -= 4;
  90. id = id_and_len & 0xFFFF;
  91. len = id_and_len >> 16;
  92.  
  93. if (align)
  94. len += (4 - len % 4) % 4;
  95. printf("debug, len: %u\n", len);
  96. printf("debug, buf and id: %p: %X\n", buf, id);
  97.  
  98. if (id == RB_ID_TERMINATOR) {
  99. break;
  100. }
  101.  
  102. if (buflen < len)
  103. break;
  104.  
  105. if (id == tag_id) {
  106. *tag_len = len;
  107. *tag_data = buf;
  108. ret = 0;
  109. break;
  110. }
  111.  
  112. buf += len;
  113. buflen -= len;
  114. }
  115.  
  116. return ret;
  117. }
  118.  
  119. inline int
  120. rb_find_hard_cfg_tag(uint16_t tag_id, uint8_t **tag_data, uint16_t *tag_len)
  121. {
  122. if (!rb_hardconfig ||
  123. !rb_hardconfig_len)
  124. return 1;
  125.  
  126. return routerboot_find_tag(rb_hardconfig,
  127. rb_hardconfig_len,
  128. tag_id, tag_data, tag_len);
  129. }
  130.  
  131. const uint8_t *
  132. rb_get_board_product_code(void)
  133. {
  134. uint16_t tag_len;
  135. uint8_t *tag;
  136. int err;
  137.  
  138. err = rb_find_hard_cfg_tag(RB_ID_BOARD_PRODUCT_CODE, &tag, &tag_len);
  139. if (err)
  140. return NULL;
  141.  
  142. return tag;
  143. }
  144.  
  145. uint32_t
  146. rb_get_board_mac(void)
  147. {
  148. uint16_t tag_len;
  149. uint8_t *tag;
  150. int err;
  151.  
  152. err = rb_find_hard_cfg_tag(RB_ID_MAC_ADDRESS_PACK, &tag, &tag_len);
  153. if (err)
  154. return 0;
  155.  
  156. return htonl(get_u32(tag));
  157. }
  158.  
  159. const uint8_t *
  160. rb_get_board_serial(void)
  161. {
  162. uint16_t tag_len;
  163. uint8_t *tag;
  164. int err;
  165.  
  166. err = rb_find_hard_cfg_tag(RB_ID_SERIAL_NUMBER, &tag, &tag_len);
  167. if (err)
  168. return NULL;
  169.  
  170. return tag;
  171. }
  172.  
  173. const uint8_t *
  174. rb_get_board_identifier(void)
  175. {
  176. uint16_t tag_len;
  177. uint8_t *tag;
  178. int err;
  179.  
  180. err = rb_find_hard_cfg_tag(RB_ID_BOARD_IDENTIFIER, &tag, &tag_len);
  181. if (err)
  182. return NULL;
  183.  
  184. return tag;
  185. }
  186.  
  187. const uint8_t *
  188. rb_get_board_name(void)
  189. {
  190. uint16_t tag_len;
  191. uint8_t *tag;
  192. int err;
  193.  
  194. err = rb_find_hard_cfg_tag(RB_ID_BOARD_NAME, &tag, &tag_len);
  195. if (err)
  196. return NULL;
  197.  
  198. return tag;
  199. }
  200.  
  201. const uint8_t *
  202. rb_get_factory_booter_version(void)
  203. {
  204. uint16_t tag_len;
  205. uint8_t *tag;
  206. int err;
  207.  
  208. err = rb_find_hard_cfg_tag(RB_ID_BIOS_VERSION, &tag, &tag_len);
  209. if (err)
  210. return NULL;
  211.  
  212. return tag;
  213. }
  214.  
  215. uint32_t
  216. rb_get_flash_info(void)
  217. {
  218. uint16_t tag_len;
  219. uint8_t *tag;
  220. int err;
  221.  
  222. err = rb_find_hard_cfg_tag(RB_ID_FLASH_INFO, &tag, &tag_len);
  223. if (err)
  224. return 0;
  225.  
  226. return htonl(get_u32(tag));
  227. }
  228.  
  229. uint32_t
  230. rb_get_hw_options(void)
  231. {
  232. uint16_t tag_len;
  233. uint8_t *tag;
  234. int err;
  235.  
  236. err = rb_find_hard_cfg_tag(RB_ID_HW_OPTIONS, &tag, &tag_len);
  237. if (err)
  238. return 0;
  239.  
  240. return htonl(get_u32(tag));
  241. }
  242.  
  243. uint8_t *
  244. __rb_get_wlan_data(void)
  245. {
  246. uint16_t tag_len;
  247. uint8_t *tag;
  248. uint16_t erd_tag_len;
  249. uint8_t *erd_tag;
  250. uint8_t *buf_lzo_in;
  251. uint8_t *buf_lzo_out;
  252. uint8_t *buf_rle_out;
  253. int err;
  254. uint32_t magic;
  255. uint32_t erd_magic;
  256. uint32_t erd_offset;
  257. size_t lzo_out_len;
  258.  
  259. err = rb_find_hard_cfg_tag(RB_ID_WLAN_DATA, &tag, &tag_len);
  260. if (err) {
  261. printf("no calibration data found\n");
  262. goto err;
  263. }
  264.  
  265. buf_lzo_in = malloc(RB_ART_SIZE);
  266. if (buf_lzo_in == NULL) {
  267. printf("no memory for calibration data\n");
  268. goto err;
  269. }
  270.  
  271. buf_rle_out = malloc(RB_ART_SIZE);
  272. if (buf_rle_out == NULL) {
  273. printf("no memory for calibration data\n");
  274. goto err_free_lzo_out;
  275. }
  276.  
  277. buf_lzo_out = malloc(RB_ART_SIZE);
  278. if (buf_lzo_out == NULL) {
  279. printf("no memory for calibration data\n");
  280. goto err_free_lzo_in;
  281. }
  282.  
  283. magic = get_u32(tag);
  284. if (magic == RB_MAGIC_LZOR) {
  285. tag += 4;
  286. tag_len -= 4;
  287. if (tag_len + sizeof(lzo_prefix) > RB_ART_SIZE) {
  288. printf("Calibration data too large\n");
  289. goto err_free_lzo_in;
  290. }
  291. printf("Copying fixed LZO prefix (size: %d)\n", sizeof(lzo_prefix));
  292. memcpy(buf_lzo_in, lzo_prefix, sizeof(lzo_prefix));
  293.  
  294. printf("Copying input data (size: %d)\n", tag_len);
  295. memcpy(buf_lzo_in + sizeof(lzo_prefix), tag, tag_len);
  296.  
  297. printf("Decompressing with LZO\n");
  298. lzo_out_len = RB_ART_SIZE;
  299. err = lzo1x_decompress_safe(buf_lzo_in, tag_len + sizeof(lzo_prefix),
  300. buf_lzo_out, &lzo_out_len, NULL);
  301. /* For some reason, I get this "input not consumed" error
  302. * even though the output is correct, so ignore it. */
  303. if (err && err != LZO_E_INPUT_NOT_CONSUMED) {
  304. printf("unable to decompress calibration data: %d\n",
  305. err);
  306. goto err_free_lzo_out;
  307. }
  308.  
  309. printf("Looking for ERD data in decompressed output\n");
  310. erd_magic = 0;
  311. for (erd_offset = 0; erd_offset < lzo_out_len; erd_offset++) {
  312. erd_magic = get_u32(buf_lzo_out + erd_offset);
  313. if (erd_magic == RB_MAGIC_ERD)
  314. break;
  315. }
  316. if (erd_magic != RB_MAGIC_ERD) {
  317. printf("no ERD data found\n");
  318. goto err_free_lzo_out;
  319. }
  320. printf("Found ERD magic at offset %d\n", erd_offset);
  321.  
  322. err = routerboot_find_tag(buf_lzo_out + erd_offset,
  323. lzo_out_len - erd_offset,
  324. 0x1, &erd_tag, &erd_tag_len);
  325. if (err) {
  326. printf("No ERD chunk found\n");
  327. goto err_free_lzo_out;
  328. }
  329.  
  330. printf("Decompress ERD data with RLE\n");
  331. err = rle_decode(erd_tag, erd_tag_len, buf_rle_out, RB_ART_SIZE,
  332. NULL, NULL);
  333. if (err) {
  334. printf("unable to decode ERD data\n");
  335. goto err_free_rle_out;
  336. }
  337. }
  338. /* Older ath79-based boards directly show the RB_MAGIC_ERD bytes followed by
  339. the LZO-compressed calibration data with no RLE */
  340. if (magic == RB_MAGIC_ERD) {
  341. if (tag_len > RB_ART_SIZE) {
  342. printf("Calibration data too large\n");
  343. goto err_free_lzo_in;
  344. }
  345.  
  346. err = routerboot_find_tag(tag, tag_len,
  347. 0x1, &buf_lzo_in, &erd_tag_len);
  348. if (err) {
  349. printf("No ERD chunk found\n");
  350. goto err_free_lzo_out;
  351. }
  352.  
  353. printf("Decompressing with LZO in ERD MAGIC\n");
  354. lzo_out_len = RB_ART_SIZE;
  355. err = lzo1x_decompress_safe(buf_lzo_in, tag_len,
  356. buf_lzo_out, &lzo_out_len, NULL);
  357. /* For some reason, I get this "input not consumed" error
  358. * even though the output is correct, so ignore it. */
  359. if (err && err != LZO_E_INPUT_NOT_CONSUMED) {
  360. printf("unable to decompress calibration data: %d\n",
  361. err);
  362. goto err_free_lzo_out;
  363. }
  364.  
  365. buf_rle_out = buf_lzo_out;
  366. }
  367. return buf_rle_out;
  368.  
  369. err_free_rle_out:
  370. free(buf_rle_out);
  371. err_free_lzo_out:
  372. free(buf_lzo_out);
  373. err_free_lzo_in:
  374. free(buf_lzo_in);
  375. err:
  376. return NULL;
  377. }
  378.  
  379. int
  380. main(int argc, char **argv)
  381. {
  382. FILE *infile;
  383. FILE *outfile;
  384. uint8_t *buf;
  385. uint32_t magic;
  386. uint32_t i;
  387.  
  388. if(argc < 2){
  389. printf("Not enough arguments\n");
  390. printf("Use -h for help\n");
  391. exit(1);
  392. }
  393.  
  394. if(strcmp(argv[1], "-h") == 0){
  395. printf("This program can extract various data from MikroTik devices hard_config partition\n");
  396. printf("Usage: rbextract <options> <hard_config_location> <output_file> (Optional)\n");
  397. printf("Options:\n");
  398. printf("-a Prints all possible info\n");
  399. printf("-n Prints board name\n");
  400. printf("-p Prints board product code\n");
  401. printf("-i Prints board identifier\n");
  402. printf("-s Prints board serial number\n");
  403. printf("-m Prints board MAC\n");
  404. printf("-o Prints board HW options\n");
  405. printf("-r Prints board RouterBoot factory version\n");
  406. printf("-f Prints board flash identifier\n");
  407. printf("-e Extract board radio calibration\n");
  408. printf("hard_config_location: Path to hard_config partiton\n");
  409. printf("output_file: Path to where caldata will be output\n");
  410. } else {
  411. infile = fopen(argv[2], "r");
  412.  
  413. if(infile == NULL){
  414. printf("Cant open given path\n");
  415. return 1;
  416. }
  417.  
  418. fseek(infile, 0L, SEEK_END);
  419. rb_hardconfig_len = ftell(infile);
  420.  
  421. fseek(infile, 0L, SEEK_SET);
  422.  
  423. rb_hardconfig = (uint8_t*)calloc(rb_hardconfig_len, sizeof(uint8_t));
  424. if(rb_hardconfig == NULL)
  425. return 1;
  426.  
  427. fread(rb_hardconfig, sizeof(uint8_t), rb_hardconfig_len, infile);
  428. fclose(infile);
  429.  
  430. magic = get_u32(rb_hardconfig);
  431. if(magic != RB_MAGIC_HARD){
  432. printf("Routerboot Hard Config not found\n");
  433. exit(1);
  434. }
  435.  
  436. if(strcmp(argv[1], "-a") == 0){
  437. printf("Board name: %s\n", rb_get_board_name());
  438. printf("Board product code: %s\n", rb_get_board_product_code());
  439. printf("Board identifier: %s\n", rb_get_board_identifier());
  440. printf("Board serial: %s\n", rb_get_board_serial());
  441. printf("Board MAC: %X\n", rb_get_board_mac());
  442. printf("HW Options %x\n", rb_get_hw_options());
  443. printf("Factory RouterBoot version: %s\n", rb_get_factory_booter_version());
  444. printf("Flash identifier: %x\n", rb_get_flash_info());
  445. } else if(strcmp(argv[1], "-n") == 0){
  446. printf("%s\n", rb_get_board_name());
  447. } else if(strcmp(argv[1], "-p") == 0){
  448. printf("%s\n", rb_get_board_product_code());
  449. } else if(strcmp(argv[1], "-i") == 0){
  450. printf("%s\n", rb_get_board_identifier());
  451. } else if(strcmp(argv[1], "-s") == 0){
  452. printf("%s\n", rb_get_board_serial());
  453. } else if(strcmp(argv[1], "-m") == 0){
  454. printf("%x\n", rb_get_board_mac());
  455. } else if(strcmp(argv[1], "-o") == 0){
  456. printf("%x\n", rb_get_hw_options());
  457. } else if(strcmp(argv[1], "-r") == 0){
  458. printf("%s\n", rb_get_factory_booter_version());
  459. } else if(strcmp(argv[1], "-f") == 0){
  460. printf("%x\n", rb_get_flash_info());
  461. } else if(strcmp(argv[1], "-e") == 0){
  462. buf = __rb_get_wlan_data();
  463. if (buf == NULL) {
  464. printf("Could not extract calibration data\n");
  465. return 1;
  466. }
  467.  
  468. if(argv[3] == NULL){
  469. printf("Missing output file argument\n");
  470. return 1;
  471. }
  472.  
  473. outfile = fopen(argv[3], "wb");
  474. if(outfile == NULL){
  475. printf("Cant open given path\n");
  476. return 1;
  477. }
  478.  
  479. /* Write 65536 bytes of caldata */
  480. for(i = 0; i<RB_ART_SIZE; i++){
  481. fwrite(&buf[i], sizeof(uint8_t), sizeof(uint8_t), outfile);
  482. }
  483. fclose(outfile);
  484. }
  485. }
  486. exit(0);
  487. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement