forked from astronomer80/ota-dfu-python
-
Notifications
You must be signed in to change notification settings - Fork 4
/
gen_dat.c
135 lines (116 loc) · 3.17 KB
/
gen_dat.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* gen_dat.c -- generate a *.dat file from a *.bin file
*
* Compile: gcc gen_dat.c -o gen_dat
* NOTE: move executable to app's gcc directory.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/*
* Minimalistic INIT file structure
* See Nordic docs for INIT (*.dat) file format details.
*/
typedef struct {
uint16_t device_type;
uint16_t device_rev;
uint32_t app_version;
uint16_t softdevice_1;
uint16_t softdevice_2;
uint16_t crc;
} dfu_init_t;
static dfu_init_t dfu_init = {
.device_type = 0xffff,
.device_rev = 0xffff,
.app_version = 0xffffffff,
.softdevice_1 = 0x0001,
.softdevice_2 = 0xfffe, // Any softdevice
.crc = 0x0000,
};
/*
* This CRC code was liberated from the Nordic SDK.
* That way it exactly matched the algrithm used by the bootloader.
*/
uint16_t crc16_compute(const uint8_t * p_data,
uint32_t size,
const uint16_t * p_crc)
{
uint32_t i;
uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc;
for (i = 0; i < size; i++) {
crc = (unsigned char)(crc >> 8) | (crc << 8);
crc ^= p_data[i];
crc ^= (unsigned char)(crc & 0xff) >> 4;
crc ^= (crc << 8) << 4;
crc ^= ((crc & 0xff) << 4) << 1;
}
return crc;
}
/*
* Given an input bin file, generate a matching dat file.
*/
int main(int argc, char* argv[])
{
char * binfilename = NULL;
char * datfilename = NULL;
FILE * binfile = NULL;
FILE * datfile = NULL;
size_t binsize = 0;
uint8_t * bindata = NULL;
uint16_t crc = 0;
/*
* USAGE: gen_dat bin-filename dat-filename
*/
if (argc < 3)
return -1;
binfilename = argv[1];
datfilename = argv[2];
/* Open bin file for reads. */
binfile = fopen(binfilename, "r");
if (binfile == NULL) {
fprintf(stderr, "bin file open failed: %s\n", strerror(errno));
return -1;
}
/* Open dat file for writes. */
datfile = fopen(datfilename, "wb");
if (datfile == NULL) {
fprintf(stderr, "dat file open failed: %s\n", strerror(errno));
fclose(binfile);
return -1;
}
/* Detrmine size of bin file in bytes. */
fseek(binfile, 0L, SEEK_END);
binsize = ftell(binfile);
fseek(binfile, 0L, SEEK_SET);
if (binsize == 0) {
fprintf(stderr, "bin file size determination failed");
fclose(datfile);
fclose(binfile);
return -1;
}
/* Allocate buffer to hold all of bin file. */
bindata = (uint8_t*) malloc(binsize);
if (bindata == NULL) {
fprintf(stderr, "malloc failed");
fclose(datfile);
fclose(binfile);
return -1;
}
/* Fill buffer with bin file data. */
fread(bindata, binsize, 1, binfile);
/* Compute CRC-16. */
dfu_init.crc = crc16_compute(bindata, binsize, 0);
/*
* Write INIT file
*/
printf("Writing .dat file, size: %d\n", sizeof(dfu_init_t));
fwrite(&dfu_init, sizeof(dfu_init_t), 1, datfile);
/*
* Close all files
*/
fclose(datfile);
fclose(binfile);
return 0;
}