1
0
Fork 0

WIP shitshow

This commit is contained in:
Shawn Nock 2019-05-02 16:54:43 +00:00
parent fa35034fd6
commit 50c30b0822
5 changed files with 259 additions and 6 deletions

View File

@ -54,10 +54,12 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
*pos++ = base64_table[in[2] & 0x3f]; *pos++ = base64_table[in[2] & 0x3f];
in += 3; in += 3;
line_len += 4; line_len += 4;
/*
if (line_len >= 72) { if (line_len >= 72) {
*pos++ = '\n'; *pos++ = '\n';
line_len = 0; line_len = 0;
} }
*/
} }
if (end - in) { if (end - in) {

77
src/crc.h Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2019 Shawn Nock <shawn@monadnock.ca>
* Copyright (c) 2018 Workaround GmbH.
* Copyright (c) 2017 Intel Corporation.
* Copyright (c) 2017 Nordic Semiconductor ASA
* Copyright (c) 2015 Runtime Inc
* Copyright (c) 2018 Google LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/
/** @file
* @brief CRC computation function
*/
#ifndef ZEPHYR_INCLUDE_CRC_H_
#define ZEPHYR_INCLUDE_CRC_H_
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup checksum Checksum
*/
/**
* @defgroup crc CRC
* @ingroup checksum
* @{
*/
/**
* @brief Generic function for computing CRC 16
*
* Compute CRC 16 by passing in the address of the input, the input length
* and polynomial used in addition to the initial value.
*
* @param src Input bytes for the computation
* @param len Length of the input in bytes
* @param polynomial The polynomial to use omitting the leading x^16
* coefficient
* @param initial_value Initial value for the CRC computation
* @param pad Adds padding with zeros at the end of input bytes
*
* @return The computed CRC16 value
*/
uint16_t crc16(const uint8_t *src, size_t len, uint16_t polynomial,
uint16_t initial_value, bool pad);
/**
* @brief Compute ANSI variant of CRC 16
*
* ANSI variant of CRC 16 is using 0x8005 as its polynomial with the initial
* value set to 0xffff.
*
* @param src Input bytes for the computation
* @param len Length of the input in bytes
*
* @return The computed CRC16 value
*/
static inline uint16_t crc16_ansi(const uint8_t *src, size_t len)
{
return crc16(src, len, 0x8005, 0xffff, true);
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

40
src/crc16_sw.c Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "crc.h"
uint16_t crc16(const uint8_t *src, size_t len, uint16_t polynomial,
uint16_t initial_value, bool pad)
{
uint16_t crc = initial_value;
size_t padding = pad ? sizeof(crc) : 0;
size_t i, b;
/* src length + padding (if required) */
for (i = 0; i < len + padding; i++) {
for (b = 0; b < 8; b++) {
uint16_t divide = crc & 0x8000UL;
crc = (crc << 1U);
/* choose input bytes or implicit trailing zeros */
if (i < len) {
crc |= !!(src[i] & (0x80U >> b));
}
if (divide != 0U) {
crc = crc ^ polynomial;
}
}
}
return crc;
}

View File

@ -7,16 +7,25 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "base64.h" #include "base64.h"
#include "crc.h"
#include "image.h" #include "image.h"
#include "nmgr.h" #include "nmgr.h"
#include "cbor.h" #include "cbor.h"
#define IMAGE_CHUNK_SIZE 60
#define CRC16_INITIAL_CRC 0 /* what to seed crc16 with */
#define CRC_CITT_POLYMINAL 0x1021
static int serial_fd = -1; static int serial_fd = -1;
void image_help(void){ void image_help(void){
printf("umcumgr image [version|upload]\n"); fprintf(stderr, "umcumgr image [version|upload]\n");
exit(1);
} }
static char *hex(char in) { static char *hex(char in) {
@ -87,8 +96,17 @@ static void do_version(void) {
assert_pkt_start(tmp); assert_pkt_start(tmp);
size_t out_len; size_t out_len;
if (in_len < 2) {
fprintf(stderr, "packet too small, bailing");
exit(5);
}
uint8_t *decoded_buf = base64_decode(tmp+2, in_len-2, &out_len); uint8_t *decoded_buf = base64_decode(tmp+2, in_len-2, &out_len);
if (!decoded_buf) {
fprintf(stderr, "Failed to decode base64, bailing\n");
exit(5);
}
// Unclear why this would be useful in a line oriented (cannonical mode) program // Unclear why this would be useful in a line oriented (cannonical mode) program
uint8_t *p = decoded_buf; uint8_t *p = decoded_buf;
uint16_t pkt_len = ntohs(*(uint16_t *)p); uint16_t pkt_len = ntohs(*(uint16_t *)p);
@ -130,8 +148,119 @@ static void do_version(void) {
free(decoded_buf); free(decoded_buf);
} }
void do_upload(void){ static void wrap_and_send_pkt(uint8_t *data, size_t len) {
return; uint8_t b64_buf[BOOT_SERIAL_OUT_MAX];
struct nmgr_hdr hdr;
hdr.nh_op = NMGR_OP_WRITE;
hdr.nh_group = htons(MGMT_GROUP_ID_IMAGE);
hdr.nh_id = IMGMGR_NMGR_ID_UPLOAD;
uint16_t crc = crc16((uint8_t*)&hdr, sizeof(struct nmgr_hdr), CRC_CITT_POLYMINAL, CRC16_INITIAL_CRC, false);
crc = crc16(data, len, CRC_CITT_POLYMINAL, crc, true);
crc = htons(crc);
uint16_t tot_len = len + sizeof(struct nmgr_hdr) + sizeof(crc);
uint16_t net_len = htons(tot_len);
uint8_t *pos = b64_buf;
memcpy(b64_buf, &net_len, sizeof(tot_len));
pos += sizeof(tot_len);
memcpy(pos, data, len);
pos += len;
memcpy(pos, &crc, sizeof(crc));
size_t out_len;
uint8_t *out_buf = base64_encode(b64_buf, tot_len, &out_len);
fprintf(stderr, "Trying to wrap %u bytes\n", (unsigned) len);
uint8_t start[] = {SHELL_NLIP_PKT_START1, SHELL_NLIP_PKT_START2};
write(serial_fd, start, sizeof(start));
write(serial_fd, out_buf, out_len-1);
write(serial_fd, "\n", 1);
fsync(serial_fd);
free(out_buf);
}
void do_upload(char *filename){
int fd = open(filename, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Failed to open \"%s\": %s\n", filename, strerror(errno));
exit(2);
}
struct stat st;
fstat(fd, &st);
size_t pos = 0, len = st.st_size;
while (pos < len){
CborEncoder root, map;
uint8_t cbor_buf[BOOT_SERIAL_OUT_MAX];
cbor_encoder_init(&root, cbor_buf, BOOT_SERIAL_OUT_MAX, 0);
cbor_encoder_create_map(&root, &map, pos == 0 ? 3 : 2);
if (pos == 0) {
cbor_encode_text_stringz(&map, "len");
cbor_encode_int(&map, len);
}
cbor_encode_text_stringz(&map, "off");
cbor_encode_int(&map, pos);
cbor_encode_text_stringz(&map, "data");
uint8_t data[IMAGE_CHUNK_SIZE];
int actual_size;
if ((actual_size = read(fd, data, IMAGE_CHUNK_SIZE)) < IMAGE_CHUNK_SIZE) {
if (errno != 0) {
fprintf(stderr, "Error reading the firmware file: %s", strerror(errno));
exit(2);
}
}
cbor_encode_byte_string(&map, data, actual_size);
cbor_encoder_close_container(&root, &map);
wrap_and_send_pkt(data, cbor_encoder_get_buffer_size(&root, cbor_buf));
uint8_t resp_buf[BOOT_SERIAL_IN_MAX];
int in_len = read(serial_fd, &resp_buf, BOOT_SERIAL_IN_MAX);
if (in_len < 0) {
fprintf(stderr, "Failed to read from serial port: %s", strerror(errno));
exit(4);
}
if (in_len < 2) {
fprintf(stderr, "packet too small, bailing");
exit(5);
}
printlen(resp_buf, in_len);
fflush(stdout);
size_t out_len;
uint8_t *out = base64_decode(resp_buf+2, in_len-2, &out_len);
CborParser parser;
CborValue it, rc;
cbor_parser_init(out, out_len, 0, &parser, &it);
cbor_require_type(&it, CborMapType);
if (cbor_value_map_find_value(&it, "rc", &rc)) {
fprintf(stderr, "Failed to find an response code %s:%d\n", __FILE__, __LINE__);
}
int r;
cbor_value_get_int(&rc, &r);
if (!r) {
fprintf(stderr, "Got an error response to a sent chunk, bailing\n");
exit(3);
}
if (cbor_value_map_find_value(&it, "off", &rc)) {
fprintf(stderr, "Failed to find an offset in the response %s:%d\n", __FILE__, __LINE__);
} else {
cbor_value_get_int(&rc, &r);
printf("Wrote %d\n", r);
}
pos += actual_size;
}
} }
void image_main(int fd, int argc, char **argv){ void image_main(int fd, int argc, char **argv){
@ -143,7 +272,10 @@ void image_main(int fd, int argc, char **argv){
if (!strcmp(argv[0], "version")) { if (!strcmp(argv[0], "version")) {
do_version(); do_version();
} else if (!strcmp(argv[0], "upload")) { } else if (!strcmp(argv[0], "upload")) {
do_upload(); if (argc < 2) {
fprintf(stderr, "umcumgr image upload <binary file>\n");
}
do_upload(argv[1]);
} else { } else {
image_help(); image_help();
} }

View File

@ -26,7 +26,7 @@ int main(int argc, char **argv) {
} }
} }
int serial_fd = open(serial_port, O_RDWR | O_NOCTTY); int serial_fd = open(serial_port, O_RDWR | O_NOCTTY | O_NDELAY);
if (serial_fd < 0) { if (serial_fd < 0) {
fprintf(stderr, "Unable to open %s: %s\n", serial_port, strerror(errno)); fprintf(stderr, "Unable to open %s: %s\n", serial_port, strerror(errno));
return 1; return 1;
@ -44,9 +44,11 @@ int main(int argc, char **argv) {
return 2; return 2;
} }
t_options.c_cflag[]
if (tcsetattr(serial_fd, TCSANOW, &t_options) < 0){ if (tcsetattr(serial_fd, TCSANOW, &t_options) < 0){
fprintf(stderr, "Failed to set termios attrs.\n"); fprintf(stderr, "Failed to set termios attrs.\n");
} }
tcflush(serial_fd, TCIOFLUSH);
uint8_t rem = (uint8_t)(argc - optind); uint8_t rem = (uint8_t)(argc - optind);
if (rem) { if (rem) {