2019-03-26 14:24:36 -04:00
|
|
|
//
|
|
|
|
// Created by nock on 26/03/19.
|
|
|
|
//
|
|
|
|
|
2019-05-01 12:25:19 -04:00
|
|
|
#include <errno.h>
|
2019-03-26 14:24:36 -04:00
|
|
|
#include <stdio.h>
|
2019-05-01 12:25:19 -04:00
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2019-05-02 08:48:43 -04:00
|
|
|
#include <netinet/in.h>
|
2019-05-01 12:25:19 -04:00
|
|
|
|
2019-05-02 08:48:43 -04:00
|
|
|
#include "base64.h"
|
2019-03-26 14:24:36 -04:00
|
|
|
#include "image.h"
|
2019-05-01 12:25:19 -04:00
|
|
|
#include "nmgr.h"
|
2019-05-02 08:48:43 -04:00
|
|
|
#include "cbor.h"
|
|
|
|
|
|
|
|
static int serial_fd = -1;
|
2019-05-01 12:25:19 -04:00
|
|
|
|
|
|
|
void image_help(void){
|
2019-05-02 08:48:43 -04:00
|
|
|
printf("umcumgr image [version|upload]\n");
|
2019-05-01 12:25:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *hex(char in) {
|
|
|
|
static char out[3] = {0};
|
|
|
|
static char lookup[] = {
|
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
|
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
|
|
|
};
|
|
|
|
out[0] = lookup[in >> 4];
|
|
|
|
out[1] = lookup[in & 0xf];
|
|
|
|
out[2] = 0;
|
|
|
|
return out;
|
|
|
|
}
|
2019-03-26 14:24:36 -04:00
|
|
|
|
2019-05-02 08:48:43 -04:00
|
|
|
static void hex_print(char *in, size_t len) {
|
|
|
|
char tmp[len*2+1];
|
|
|
|
tmp[len] = 0;
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
strcat(tmp, hex(in[i]));
|
|
|
|
}
|
|
|
|
printf("%s\n", tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printlen(uint8_t *src, size_t len){
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
putchar(src[i]);
|
|
|
|
}
|
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
static void assert_pkt_start(uint8_t *buf){
|
|
|
|
assert(buf[0] == SHELL_NLIP_PKT_START1);
|
|
|
|
assert(buf[1] == SHELL_NLIP_PKT_START2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cbor_require_type(CborValue *it, CborType type) {
|
|
|
|
CborType actual_type = cbor_value_get_type(it);
|
|
|
|
if (actual_type != type) {
|
|
|
|
fprintf(stderr, "Cbor deserialization error. Expected type %d, received %d\n", type, actual_type);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_version(void) {
|
|
|
|
int rc = write(serial_fd, IMAGE_LIST_CMD, sizeof(IMAGE_LIST_CMD) - 1);
|
|
|
|
if (rc < sizeof(IMAGE_LIST_CMD) - 1) {
|
|
|
|
fprintf(stderr, "Failed to send command: %s", strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
uint8_t tmp[BOOT_SERIAL_IN_MAX];
|
|
|
|
int in_len;
|
|
|
|
while (1) {
|
|
|
|
if ((in_len = read(serial_fd, tmp, BOOT_SERIAL_IN_MAX)) < 0) {
|
|
|
|
if (errno == EAGAIN) {
|
|
|
|
fprintf(stderr, "non-blocking\n");
|
|
|
|
continue;
|
2019-05-01 12:25:19 -04:00
|
|
|
}
|
2019-05-02 08:48:43 -04:00
|
|
|
fprintf(stderr, "Reading from serial failed: %s\n", strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process the response
|
|
|
|
CborParser parser;
|
|
|
|
CborValue it;
|
|
|
|
|
|
|
|
assert_pkt_start(tmp);
|
|
|
|
size_t out_len;
|
|
|
|
|
|
|
|
uint8_t *decoded_buf = base64_decode(tmp+2, in_len-2, &out_len);
|
|
|
|
|
|
|
|
// Unclear why this would be useful in a line oriented (cannonical mode) program
|
|
|
|
uint8_t *p = decoded_buf;
|
|
|
|
uint16_t pkt_len = ntohs(*(uint16_t *)p);
|
|
|
|
fflush(stdout);
|
|
|
|
p += sizeof(pkt_len);
|
|
|
|
|
|
|
|
// Hdr also seems a bit pointless, maybe could check for success before CBOR deserialization?
|
|
|
|
struct nmgr_hdr hdr;
|
|
|
|
memcpy(&hdr, p, sizeof(struct nmgr_hdr));
|
|
|
|
p += sizeof(struct nmgr_hdr);
|
|
|
|
cbor_parser_init(p, out_len, 0, &parser, &it);
|
|
|
|
|
|
|
|
cbor_require_type(&it, CborMapType);
|
|
|
|
CborValue map;
|
|
|
|
cbor_value_enter_container(&it, &map);
|
|
|
|
cbor_require_type(&map, CborTextStringType);
|
|
|
|
cbor_value_advance(&map);
|
|
|
|
cbor_require_type(&map, CborArrayType);
|
|
|
|
CborValue img_array;
|
|
|
|
cbor_value_enter_container(&map, &img_array);
|
|
|
|
|
|
|
|
while (!cbor_value_at_end(&img_array)) {
|
|
|
|
assert(cbor_value_get_type(&img_array) == CborMapType);
|
|
|
|
CborValue version_tag;
|
|
|
|
CborError err = cbor_value_map_find_value(&img_array, "version", &version_tag);
|
|
|
|
if (err) {
|
|
|
|
// There's no version key for this slot, probably an error
|
|
|
|
fprintf(stderr, "Failed to find version info: %s", cbor_error_string(err));
|
|
|
|
cbor_value_advance(&img_array);
|
|
|
|
continue;
|
2019-05-01 12:25:19 -04:00
|
|
|
}
|
2019-05-02 08:48:43 -04:00
|
|
|
char *version;
|
|
|
|
size_t len;
|
|
|
|
cbor_value_dup_text_string(&version_tag, &version, &len, NULL);
|
|
|
|
printf("%s\n", version);
|
|
|
|
free(version);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(decoded_buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_upload(void){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void image_main(int fd, int argc, char **argv){
|
|
|
|
serial_fd = fd;
|
|
|
|
if (argc < 1) {
|
|
|
|
image_help();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!strcmp(argv[0], "version")) {
|
|
|
|
do_version();
|
|
|
|
} else if (!strcmp(argv[0], "upload")) {
|
|
|
|
do_upload();
|
2019-05-01 12:25:19 -04:00
|
|
|
} else {
|
|
|
|
image_help();
|
|
|
|
}
|
2019-03-26 14:24:36 -04:00
|
|
|
}
|