Skip to content

Instantly share code, notes, and snippets.

@pixel-stuck
Last active November 19, 2019 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pixel-stuck/b87ca37a7e5de9af5e53040a3e95bf1a to your computer and use it in GitHub Desktop.
Save pixel-stuck/b87ca37a7e5de9af5e53040a3e95bf1a to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef struct __attribute__((packed)) uf2_block
{
uint32_t magic_begin_string;
uint32_t magic_begin_random;
uint32_t flags;
uint32_t addr;
uint32_t data_size;
uint32_t block_num;
uint32_t total_blocks;
uint32_t family_id;
uint8_t data[476];
uint32_t magic_end;
} uf2_block_t;
enum uf2_flags
{
skip = 1,
file_container = 0x1000,
family_id_present = 0x2000,
checksum_present = 0x4000
};
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("Please specify an input file.\n");
}
printf("converting file %s...\n", argv[1]);
size_t arg_str_len = strlen(argv[1]);
char *out_str;
if(!strcmp(".uf2", &argv[1][arg_str_len - 4]) || !strcmp(".UF2", &argv[1][arg_str_len - 4]))
{
out_str = malloc(arg_str_len + 1);
memset(out_str, 0, arg_str_len + 1);
strncpy(out_str, argv[1], arg_str_len - 4);
strcat(out_str, ".bin");
}
else
{
out_str = malloc(strlen("output.bin") + 1);
strcpy(out_str, "output.bin");
}
FILE *uf2_file = fopen(argv[1], "rb");
FILE *out_file = fopen(out_str, "wb");
if(!uf2_file)
{
printf("Failed to open %s\n", argv[1]);
return -1;
}
if(!out_file)
{
printf("Failed to open output file %s\n", out_str);
return -1;
}
struct stat uf2_stat;
if(stat(argv[1], &uf2_stat) < 0)
{
printf("Failed to stat %s!\nPlease make sure the file exists.\n", argv[1]);
return -1;
}
size_t uf2_size = uf2_stat.st_size;
uf2_block_t block;
for(int i = 0; i < uf2_size / 0x200; i++)
{
fread(&block, 1, 0x200, uf2_file);
if(block.magic_begin_string == 0x0A324655 && block.magic_begin_random == 0x9E5D5157 && block.magic_end == 0x0AB16F30 && block.flags != skip)
{
if(block.addr >= 0x2000) /* The bootloader lives in the range 0-0x1FFF, make sure we're outside of the bootloader. */
{
fseek(out_file, block.addr - 0x2000, SEEK_SET);
fwrite(&block.data[0], 1, block.data_size, out_file);
}
}
}
printf("Finished conversion!\nOutput file: %s\n", out_str);
}
using System;
using System.IO;
namespace uf2_to_bin
{
class uf2_block
{
public UInt32 magic_begin_string;
public UInt32 magic_begin_random;
public UInt32 flags;
public UInt32 addr;
public UInt32 data_size;
public UInt32 block_num;
public UInt32 total_blocks;
public UInt32 family_id;
public byte[] data;
public UInt32 magic_end;
}
class program
{
static uf2_block read_block(FileStream uf2_f)
{
uf2_block block = new uf2_block();
byte[] tmp = new byte[4];
uf2_f.Read(tmp, 0, 4);
block.magic_begin_string = Convert.ToUInt32(tmp);
if(block.magic_begin_string != 0x0A324655)
return null;
uf2_f.Read(tmp, 0, 4);
block.magic_begin_random = Convert.ToUInt32(tmp);
if(block.magic_begin_random != 0x9E5D5157)
return null;
uf2_f.Read(tmp, 0, 4);
block.flags = Convert.ToUInt32(tmp);
if((block.flags & 1) == 1)
return null;
uf2_f.Read(tmp, 0, 4);
block.addr = Convert.ToUInt32(tmp);
if(block.addr < 0x2000)
return null;
uf2_f.Read(tmp, 0, 4);
block.data_size = Convert.ToUInt32(tmp);
if(block.data_size > 476)
return null;
uf2_f.Read(tmp, 0, 4);
block.block_num = Convert.ToUInt32(tmp);
uf2_f.Read(tmp, 0, 4);
block.total_blocks = Convert.ToUInt32(tmp);
uf2_f.Read(tmp, 0, 4);
block.family_id = Convert.ToUInt32(tmp);
uf2_f.Read(block.data, 0, 476);
uf2_f.Read(tmp, 0, 4);
block.magic_end = Convert.ToUInt32(tmp);
if(block.magic_end != 0x0AB16F30)
return null;
return block;
}
static void main(string[] args)
{
if(args.length < 2)
{
Console.WriteLine("Please specify a file!\n");
return 1;
}
FileStream uf2_f = new FileStream(args[1], FileMode.Open, FileAccess.Read); //open new file as read-only.
FileStream out_f = new FileStream("output.bin", FileMode.CreateNew, FileAccess.Write); //creates new file and opens as write-only
long uf2_len = uf2_f.Length
for(long i = 0; i < uf2_len / 0x200; i++)
{
uf2_block block = read_block(uf2_f);
if(block != null)
{
out_f.Write(block.data, block.addr - 0x2000, block.data_size);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment