uf2/
lib.rs

1extern crate byteorder;
2
3use std::io::prelude::*;
4
5use byteorder::{LittleEndian, WriteBytesExt};
6
7const UF2_MAGIC_START0: u32 = 0x0A324655; // "UF2\n"
8const UF2_MAGIC_START1: u32 = 0x9E5D5157; // Randomly selected
9const UF2_MAGIC_END: u32    = 0x0AB16F30; // Ditto
10
11pub fn bin_to_uf2(bytes: &Vec<u8>, family_id: u32, app_start_addr: u32) -> Result<Vec<u8>, std::io::Error> {
12    let datapadding = [0u8; 512-256-32-4];
13    let nblocks: u32 = ((bytes.len() + 255) / 256) as u32;
14    let mut outp: Vec<u8> = Vec::new();
15    for blockno in 0..nblocks {
16        let ptr = 256 * blockno;
17        let chunk = match bytes.get(ptr as usize..ptr as usize+256) {
18            Some(bytes) => bytes.to_vec(),
19            None => {
20                let mut chunk = bytes[ptr as usize..bytes.len()].to_vec();
21                while chunk.len() < 256 {
22                    chunk.push(0);
23                }
24                chunk
25            }
26        };
27        let mut flags: u32 = 0;
28        if family_id != 0 {
29            flags |= 0x2000
30        }
31
32        // header
33        outp.write_u32::<LittleEndian>(UF2_MAGIC_START0)?;
34        outp.write_u32::<LittleEndian>(UF2_MAGIC_START1)?;
35        outp.write_u32::<LittleEndian>(flags)?;
36        outp.write_u32::<LittleEndian>(ptr + app_start_addr)?;
37        outp.write_u32::<LittleEndian>(256)?;
38        outp.write_u32::<LittleEndian>(blockno)?;
39        outp.write_u32::<LittleEndian>(nblocks)?;
40        outp.write_u32::<LittleEndian>(family_id)?;
41
42        // data
43        outp.write(&chunk)?;
44        outp.write(&datapadding)?;
45
46        // footer
47        outp.write_u32::<LittleEndian>(UF2_MAGIC_END)?;
48    }
49    Ok(outp)
50}
51