WIP shitshow
This commit is contained in:
parent
fa35034fd6
commit
50c30b0822
|
@ -54,10 +54,12 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
|
|||
*pos++ = base64_table[in[2] & 0x3f];
|
||||
in += 3;
|
||||
line_len += 4;
|
||||
if (line_len >= 72) {
|
||||
/*
|
||||
if (line_len >= 72) {
|
||||
*pos++ = '\n';
|
||||
line_len = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (end - in) {
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
140
src/image.c
140
src/image.c
|
@ -7,16 +7,25 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "base64.h"
|
||||
#include "crc.h"
|
||||
#include "image.h"
|
||||
#include "nmgr.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;
|
||||
|
||||
void image_help(void){
|
||||
printf("umcumgr image [version|upload]\n");
|
||||
fprintf(stderr, "umcumgr image [version|upload]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static char *hex(char in) {
|
||||
|
@ -87,8 +96,17 @@ static void do_version(void) {
|
|||
assert_pkt_start(tmp);
|
||||
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);
|
||||
|
||||
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
|
||||
uint8_t *p = decoded_buf;
|
||||
uint16_t pkt_len = ntohs(*(uint16_t *)p);
|
||||
|
@ -130,8 +148,119 @@ static void do_version(void) {
|
|||
free(decoded_buf);
|
||||
}
|
||||
|
||||
void do_upload(void){
|
||||
return;
|
||||
static void wrap_and_send_pkt(uint8_t *data, size_t len) {
|
||||
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){
|
||||
|
@ -143,7 +272,10 @@ void image_main(int fd, int argc, char **argv){
|
|||
if (!strcmp(argv[0], "version")) {
|
||||
do_version();
|
||||
} else if (!strcmp(argv[0], "upload")) {
|
||||
do_upload();
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "umcumgr image upload <binary file>\n");
|
||||
}
|
||||
do_upload(argv[1]);
|
||||
} else {
|
||||
image_help();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
fprintf(stderr, "Unable to open %s: %s\n", serial_port, strerror(errno));
|
||||
return 1;
|
||||
|
@ -44,9 +44,11 @@ int main(int argc, char **argv) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
t_options.c_cflag[]
|
||||
if (tcsetattr(serial_fd, TCSANOW, &t_options) < 0){
|
||||
fprintf(stderr, "Failed to set termios attrs.\n");
|
||||
}
|
||||
tcflush(serial_fd, TCIOFLUSH);
|
||||
|
||||
uint8_t rem = (uint8_t)(argc - optind);
|
||||
if (rem) {
|
||||
|
|
Loading…
Reference in New Issue