Skip to content

Commit c39e11f

Browse files
committed
feat: add input format support to verify command
The verify command now supports Intel HEX and Motorola S-record files in addition to raw binary. The format is auto-detected from extension or can be explicitly specified with --input-format (-f). When using files with embedded address information and no explicit address is provided with -a, the embedded address is used automatically. Signed-off-by: Vincent Jardin <vjardin@free.fr>
1 parent 21cf2e8 commit c39e11f

File tree

4 files changed

+44
-46
lines changed

4 files changed

+44
-46
lines changed

radfu.h2m

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@ the written data matches the file.
8181

8282
.TP
8383
.B verify <file>
84-
Verify flash memory contents against a binary file. Compares the flash region
85-
with the file and reports the first mismatch if any. Use \fB-a\fR to specify
86-
the start address and \fB-s\fR for the size. If size is omitted, verifies
87-
the file size.
84+
Verify flash memory contents against a firmware file. Supports binary, Intel HEX,
85+
and Motorola S-record formats. Use \fB-f\fR to specify the format (auto-detected
86+
by default from extension). Use \fB-a\fR to specify the start address (if omitted
87+
and the file contains address information, the embedded address is used). Use
88+
\fB-s\fR to specify the size. If size is omitted, verifies the file size.
89+
Reports the first mismatch if any.
8890

8991
.TP
9092
.B erase
@@ -132,8 +134,9 @@ Supported rates depend on the MCU's SCI clock:
132134
USB communication is not affected by baud rate settings.
133135

134136
[input formats]
135-
The \fBwrite\fR command supports multiple firmware file formats. Use \fB-f\fR
136-
to explicitly specify the format, or let radfu auto-detect from the file extension.
137+
The \fBwrite\fR and \fBverify\fR commands support multiple firmware file formats.
138+
Use \fB-f\fR to explicitly specify the format, or let radfu auto-detect from the
139+
file extension.
137140

138141
.SS Supported Formats
139142
.TP
@@ -166,6 +169,8 @@ radfu write firmware.hex # Auto-detect Intel HEX, use embedded addr
166169
radfu write -f srec app.bin # Force S-record parsing on .bin file
167170
radfu write -a 0x10000 app.s19 # Override embedded address
168171
radfu write -f bin -a 0x0 data.dat # Force binary, explicit address
172+
radfu verify firmware.hex # Verify flash against Intel HEX file
173+
radfu verify -a 0x08000000 app.s19 # Verify at explicit address
169174
.fi
170175

171176
[usb vs uart]

src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ main(int argc, char *argv[]) {
599599
ret = ra_write(&dev, file, address, size, verify, input_format);
600600
break;
601601
case CMD_VERIFY:
602-
ret = ra_verify(&dev, file, address, size);
602+
ret = ra_verify(&dev, file, address, size, input_format);
603603
break;
604604
case CMD_ERASE:
605605
ret = ra_erase(&dev, address, size);

src/radfu.c

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -814,42 +814,36 @@ ra_read(ra_device_t *dev, const char *file, uint32_t start, uint32_t size) {
814814
}
815815

816816
int
817-
ra_verify(ra_device_t *dev, const char *file, uint32_t start, uint32_t size) {
817+
ra_verify(
818+
ra_device_t *dev, const char *file, uint32_t start, uint32_t size, input_format_t format) {
818819
uint8_t pkt[MAX_PKT_LEN];
819820
uint8_t resp[CHUNK_SIZE + 6];
820821
uint8_t flash_chunk[CHUNK_SIZE];
821-
uint8_t file_chunk[CHUNK_SIZE];
822822
uint8_t data[8];
823823
uint8_t ack_data[1] = { STATUS_OK };
824824
ssize_t pkt_len, n;
825825
uint32_t end;
826-
int fd;
827-
struct stat st;
826+
parsed_file_t parsed;
828827

829-
fd = open(file, O_RDONLY);
830-
if (fd < 0) {
831-
warn("failed to open %s", file);
828+
if (format_parse(file, format, &parsed) < 0)
832829
return -1;
833-
}
834830

835-
if (fstat(fd, &st) < 0) {
836-
warn("failed to stat %s", file);
837-
close(fd);
838-
return -1;
839-
}
831+
/* Use embedded address if available and no explicit address given */
832+
if (start == 0 && parsed.has_addr)
833+
start = parsed.base_addr;
840834

841-
uint32_t file_size = (uint32_t)st.st_size;
835+
uint32_t file_size = (uint32_t)parsed.size;
842836
if (size == 0)
843837
size = file_size;
844838

845839
if (size > file_size) {
846840
warnx("verify size (%u) > file size (%u)", size, file_size);
847-
close(fd);
841+
free(parsed.data);
848842
return -1;
849843
}
850844

851845
if (set_read_boundaries(dev, start, size, &end) < 0) {
852-
close(fd);
846+
free(parsed.data);
853847
return -1;
854848
}
855849

@@ -858,78 +852,73 @@ ra_verify(ra_device_t *dev, const char *file, uint32_t start, uint32_t size) {
858852

859853
pkt_len = ra_pack_pkt(pkt, sizeof(pkt), REA_CMD, data, 8, false);
860854
if (pkt_len < 0) {
861-
close(fd);
855+
free(parsed.data);
862856
return -1;
863857
}
864858

865859
if (ra_send(dev, pkt, pkt_len) < 0) {
866-
close(fd);
860+
free(parsed.data);
867861
return -1;
868862
}
869863

870864
uint32_t total_size = end - start + 1;
871865
uint32_t nr_packets = (end - start) / CHUNK_SIZE;
872866
uint32_t current_addr = start;
867+
uint32_t file_offset = 0;
873868
progress_t prog;
874869
progress_init(&prog, nr_packets + 1, "Verifying");
875870

876871
for (uint32_t i = 0; i <= nr_packets; i++) {
877872
n = ra_recv(dev, resp, CHUNK_SIZE + 6, 1000);
878873
if (n < 7) {
879874
warnx("short response during verify (%zd bytes)", n);
880-
close(fd);
875+
free(parsed.data);
881876
return -1;
882877
}
883878

884879
size_t chunk_len;
885880
if (unpack_with_error(resp, n, flash_chunk, &chunk_len, "verify read") < 0) {
886-
close(fd);
887-
return -1;
888-
}
889-
890-
/* Read corresponding chunk from file */
891-
ssize_t file_read = read(fd, file_chunk, chunk_len);
892-
if (file_read < 0) {
893-
warn("read from file failed");
894-
close(fd);
881+
free(parsed.data);
895882
return -1;
896883
}
897884

898-
/* Compare flash data with file data */
899-
size_t cmp_len = (size_t)file_read < chunk_len ? (size_t)file_read : chunk_len;
885+
/* Compare flash data with file data from parsed buffer */
886+
size_t remaining = parsed.size - file_offset;
887+
size_t cmp_len = remaining < chunk_len ? remaining : chunk_len;
900888
for (size_t j = 0; j < cmp_len; j++) {
901-
if (flash_chunk[j] != file_chunk[j]) {
889+
if (flash_chunk[j] != parsed.data[file_offset + j]) {
902890
progress_finish(&prog);
903891
warnx("verify FAILED at 0x%08X: flash=0x%02X, file=0x%02X",
904892
current_addr + (uint32_t)j,
905893
flash_chunk[j],
906-
file_chunk[j]);
907-
close(fd);
894+
parsed.data[file_offset + j]);
895+
free(parsed.data);
908896
return -1;
909897
}
910898
}
911899

912900
/* If file is shorter than flash region, remaining flash bytes should be 0xFF */
913-
if ((size_t)file_read < chunk_len) {
914-
for (size_t j = (size_t)file_read; j < chunk_len; j++) {
901+
if (cmp_len < chunk_len) {
902+
for (size_t j = cmp_len; j < chunk_len; j++) {
915903
if (flash_chunk[j] != 0xFF) {
916904
progress_finish(&prog);
917905
warnx("verify FAILED at 0x%08X: flash=0x%02X, expected=0xFF (beyond file)",
918906
current_addr + (uint32_t)j,
919907
flash_chunk[j]);
920-
close(fd);
908+
free(parsed.data);
921909
return -1;
922910
}
923911
}
924912
}
925913

914+
file_offset += cmp_len;
926915
current_addr += chunk_len;
927916

928917
/* Send ACK for all packets except the last one (per spec 6.20.3) */
929918
if (i < nr_packets) {
930919
pkt_len = ra_pack_pkt(pkt, sizeof(pkt), REA_CMD, ack_data, 1, true);
931920
if (pkt_len < 0) {
932-
close(fd);
921+
free(parsed.data);
933922
return -1;
934923
}
935924
ra_send(dev, pkt, pkt_len);
@@ -939,7 +928,7 @@ ra_verify(ra_device_t *dev, const char *file, uint32_t start, uint32_t size) {
939928
}
940929

941930
progress_finish(&prog);
942-
close(fd);
931+
free(parsed.data);
943932

944933
printf("Verify OK: %u bytes at 0x%08X match file\n", total_size, start);
945934
return 0;

src/radfu.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,13 @@ int ra_read(ra_device_t *dev, const char *file, uint32_t start, uint32_t size);
6161
/*
6262
* Verify flash memory against file
6363
* Compares flash contents with file, reports first mismatch
64+
* format: input file format (FORMAT_AUTO to detect from extension)
65+
* If file contains address info (Intel HEX, S-record) and start==0,
66+
* the embedded address is used.
6467
* Returns: 0 on success (match), -1 on error or mismatch
6568
*/
66-
int ra_verify(ra_device_t *dev, const char *file, uint32_t start, uint32_t size);
69+
int ra_verify(
70+
ra_device_t *dev, const char *file, uint32_t start, uint32_t size, input_format_t format);
6771

6872
/*
6973
* Check if flash memory region is blank (all 0xFF)

0 commit comments

Comments
 (0)