Embedded JojoPatch library. This library should work with JojoDiff - diff utility for binary files.
mJPatch is inspired by JAPatch, the goal is to rewrite JAPatch and decouple the dependencies of file management APIs to make the library could work with MCU easily no mater it supports file system or not.
- Parse JojoDiff patch file and log it for human reading to understand jojopatch file structure
- Simplify patch file data feeding, make it a single access point, do not call
getc
everywhere. - Be friendly to MCU development
- Minimize RAM and ROM cost
- User defined write buffer size, minimum zero. (Buffer could help to decrease write flash times to improve performance)
- JojoDiff and mJPatch library to speed up Delta Firmware Update Over The Air design
ESC A7
Escape character, (A7 A6
stands forMOD
action,A7 A5
stands forINS
action and so on)MOD A6
Modify original file content (pretending) and write to destination file, original and destination file address cursors increase together with same stepsINS A5
Insert new data to destination file. Original file address cursor stays unchanged, destination cursor increase accordingly.DEL A4
Delete data from original file (pretending), original file address cursor plus offset.EQL A3
Copy from original file to destination file, both address cursors increasing accordinglyBKT A2
Set original file address cursor backward, subtract offset.
Action | Original File Address | Destination File Address | Payload |
---|---|---|---|
MOD | +++ |
+++ |
Data stream |
INS | === |
+++ |
Data stream |
DEL | +++ |
=== |
Offset value |
EQL | +++ |
+++ |
Offset value |
BKT | --- |
=== |
Offset value |
+++ : address cursor move forward
--- : address cursor move backward
=== : address cursor stay unchanged
DEL, EQL, BKT
are followed by an offset value. It is coded in below principle.
- Big endian
- Encoding method is decided by the first offset byte
buf[0] First Byte | Offset Value Encoding |
---|---|
0 - 251 | buf[0] + 1 |
252 | buf[0] + buf[1] + 1 |
253 | buf[1] buf[2] (Big endian) |
254 | buf[1] buf[2] buf[3] buf[4] (Big endian) |
255 | buf[1] buf[2] buf[3] buf[4] buf[5] buf[6] buf[7] buf[8] (Big endian) |
- Each valid patch file must start with
A7
- Check and wait
A7
, eachA7
must be followed byA2 - A7
,- if other characters follows
A7
, parse program may ignoreA7
and process the character
- if other characters follows
- if
A2 - A6
is received, change to new action, reset context and sync address cursor - Keep do the same action until next action change event
A7 A7
will be merged to a singleA7
A7 (A2 - A6)
trigger action change event- single
A2 - A6
will be itself, nothing changed
A7 A3 FC 17
A7 A6 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7 A7
A7 A3 0F
A7 A6 A7 A7 A7 A7 A7 A7 A7 A7
A7 A3 13
A7 A6 A7 A7 A7 A7 A7 A7 A7 A7
A7 A3 5B
A7 A6 A3 A7 A7
A7 A3 59
ADDRESS
0 | EQL A7 A3 FC 17
EQL: Copy from 0(O) to 0(D) for 276 bytes
4 | MOD A7 A6 A7 A7 A7 A7 A7 A7 A7 A7
MOD: Modify from 276(O) 276(D) for 8 bytes
22 | EQL A7 A3 0F
EQL: Copy from 284(O) to 284(D) for 16 bytes
25 | MOD A7 A6 A7 A7 A7 A7
MOD: Modify from 300(O) 300(D) for 4 bytes
35 | EQL A7 A3 13
EQL: Copy from 304(O) to 304(D) for 20 bytes
38 | MOD A7 A6 A7 A7 A7 A7
MOD: Modify from 324(O) 324(D) for 4 bytes
48 | EQL A7 A3 5B
EQL: Copy from 328(O) to 328(D) for 92 bytes
51 | MOD A7 A6 A3 A7
MOD: Modify from 420(O) 420(D) for 2 bytes
56 | EQL A7 A3 59
EQL: Copy from 422(O) to 422(D) for 90 bytes
Patch file size: 59
Destination file size: 512
Original file size: 512 (used)
Compile the library and use to mjp
to test.
Initial mjp global object and set call backs.
typedef int (*mjp_des_wr_t)(int addr, uint8_t *buf, int len);
typedef int (*mjp_org_rd_t)(int addr);
typedef int (*mjp_copy_t)(int src, int des, int len);
int mjp_start(mjp_des_wr_t des_wr_cb, mjp_org_rd_t org_rd_cb, mjp_copy_t copy_cb);
des_wr_cb: write data block to destination file to a specified addr
org_rd_cb: read one byte from original file as specified addr
copy_cb: (optional), copy is used in EQL processing to speed up copy event
Feed patch data stream one by one, until the last byte.
Call after last byte of the patch file is fed to mjp_apply
. This function will flush write buffer.
Check main.c
for more details.
mjp_start(dfile_wr, ofile_rd, o2d_copy);
while ((dt = getc(pfile)) != EOF) {
mjp_parse(dt);
}
mjp_parse_done();
mjp_parse
and mjp_parse_done
can be use do to parse and log patch file for human reading. Usage is the same as mjp_apply
and mjp_apply_done