]>
git.zerfleddert.de Git - hmcfgusb/blob - firmware.c
ff4c8bece316181327e3b140d2507175f2d8376c
1 /* generic firmware-functions for HomeMatic
3 * Copyright (c) 2014 Michael Gernoth <michael@gernoth.net>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 #include <sys/types.h>
38 /* This might be wrong, but it works for current fw */
39 #define MAX_BLOCK_LENGTH 512
41 static uint8_t ascii_to_nibble(uint8_t a
)
45 if ((a
>= '0') && (a
<= '9')) {
47 } else if ((a
>= 'A') && (a
<= 'F')) {
49 } else if ((a
>= 'a') && (a
<= 'f')) {
56 static int validate_nibble(uint8_t a
)
58 if (((a
>= '0') && (a
<= '9')) ||
59 ((a
>= 'A') && (a
<= 'F')) ||
60 ((a
>= 'a') && (a
<= 'f')))
66 struct firmware
* firmware_read_firmware(char *filename
, int debug
)
76 fw
= malloc(sizeof(struct firmware
));
82 memset(fw
, 0, sizeof(struct firmware
));
84 if (stat(filename
, &stat_buf
) == -1) {
85 fprintf(stderr
, "Can't stat %s: %s\n", filename
, strerror(errno
));
89 fd
= open(filename
, O_RDONLY
);
91 fprintf(stderr
, "Can't open %s: %s", filename
, strerror(errno
));
95 printf("Reading firmware from %s...\n", filename
);
97 memset(buf
, 0, sizeof(buf
));
105 printf("can't get length information!\n");
109 for (i
= 0; i
< r
; i
++) {
110 if (!validate_nibble(buf
[i
])) {
111 fprintf(stderr
, "Firmware file not valid!\n");
116 len
= (ascii_to_nibble(buf
[0]) & 0xf)<< 4;
117 len
|= ascii_to_nibble(buf
[1]) & 0xf;
119 len
|= (ascii_to_nibble(buf
[2]) & 0xf)<< 4;
120 len
|= ascii_to_nibble(buf
[3]) & 0xf;
122 if (len
> MAX_BLOCK_LENGTH
) {
123 fprintf(stderr
, "Invalid block-length %u > %u for block %d!\n", len
, MAX_BLOCK_LENGTH
, fw
->fw_blocks
+1);
127 fw
->fw
= realloc(fw
->fw
, sizeof(uint8_t*) * (fw
->fw_blocks
+ 1));
128 if (fw
->fw
== NULL
) {
129 perror("Can't reallocate fw->fw-blocklist");
133 fw
->fw
[fw
->fw_blocks
] = malloc(len
+ 4);
134 if (fw
->fw
[fw
->fw_blocks
] == NULL
) {
135 perror("Can't allocate memory for fw->fw-block");
139 fw
->fw
[fw
->fw_blocks
][0] = (fw
->fw_blocks
>> 8) & 0xff;
140 fw
->fw
[fw
->fw_blocks
][1] = fw
->fw_blocks
& 0xff;
141 fw
->fw
[fw
->fw_blocks
][2] = (len
>> 8) & 0xff;
142 fw
->fw
[fw
->fw_blocks
][3] = len
& 0xff;
144 r
= read(fd
, buf
, len
* 2);
148 } else if (r
< len
* 2) {
149 fprintf(stderr
, "short read, aborting (%d < %d)\n", r
, len
* 2);
153 for (i
= 0; i
< r
; i
+=2) {
154 if ((!validate_nibble(buf
[i
])) ||
155 (!validate_nibble(buf
[i
+1]))) {
156 fprintf(stderr
, "Firmware file not valid!\n");
160 fw
->fw
[fw
->fw_blocks
][(i
/2) + 4] = (ascii_to_nibble(buf
[i
]) & 0xf)<< 4;
161 fw
->fw
[fw
->fw_blocks
][(i
/2) + 4] |= ascii_to_nibble(buf
[i
+1]) & 0xf;
166 printf("Firmware block %d with length %u read.\n", fw
->fw_blocks
, len
);
169 if (fw
->fw_blocks
== 0) {
170 fprintf(stderr
, "Firmware file not valid!\n");
174 printf("Firmware with %d blocks successfully read.\n", fw
->fw_blocks
);
179 void firmware_free(struct firmware
*fw
)
183 for (i
= 0; i
< fw
->fw_blocks
; i
++)