@@ -1365,11 +1365,41 @@ struct uf2_convert_command : public cmd {
13651365 }
13661366};
13671367
1368+ struct uf2_combine_command : public cmd {
1369+ uf2_combine_command () : cmd(" combine" ) {}
1370+ bool execute (device_map &devices) override ;
1371+ virtual device_support get_device_support () override { return none; }
1372+
1373+ group get_cli () override {
1374+ return (
1375+ option (" --quiet" ).set (settings.quiet ) % " Don't print any output" +
1376+ option (" --verbose" ).set (settings.verbose ) % " Print verbose output" +
1377+ named_typed_file_selection_x (" infile1" , 0 , " uf2" ) % " First file to combine" +
1378+ named_typed_file_selection_x (" infile1" , 1 , " uf2" ) % " Second file to combine" +
1379+ named_typed_file_selection_x (" outfile" , 2 , " uf2" ) % " File to save output to" +
1380+ (
1381+ option (" --family" ) & family_id (" family_id" ).set (settings.family_id ) % " family ID for combined UF2 (defaults to first one)"
1382+ ).force_expand_help (true ) % " UF2 Family options"
1383+ #if SUPPORT_RP2350_A2
1384+ + (
1385+ option (" --abs-block" ).set (settings.uf2 .abs_block ) % " Add an absolute block" +
1386+ hex (" abs_block_loc" ).set (settings.uf2 .abs_block_loc ).min (0 ) % " absolute block location (default to 0x10ffff00)"
1387+ ).force_expand_help (true ).min (0 ) % " Errata RP2350-E10 Fix"
1388+ #endif
1389+ );
1390+ }
1391+
1392+ string get_doc () const override {
1393+ return " Combine multiple UF2 files." ;
1394+ }
1395+ };
1396+
13681397vector<std::shared_ptr<cmd>> uf2_sub_commands {
13691398 #if HAS_LIBUSB
13701399 std::shared_ptr<cmd>(new uf2_info_command ()),
13711400 #endif
13721401 std::shared_ptr<cmd>(new uf2_convert_command ()),
1402+ std::shared_ptr<cmd>(new uf2_combine_command ()),
13731403};
13741404
13751405struct uf2_command : public multi_cmd {
@@ -6742,6 +6772,86 @@ bool uf2_convert_command::execute(device_map &devices) {
67426772 return false ;
67436773}
67446774
6775+ bool uf2_combine_command::execute (device_map &devices) {
6776+ if (get_file_type_idx (0 ) != filetype::uf2 || get_file_type_idx (1 ) != filetype::uf2 || get_file_type_idx (0 ) != filetype::uf2) {
6777+ fail (ERROR_ARGS, " All files must be UF2 files\n " );
6778+ }
6779+
6780+ auto file1 = get_file_idx (ios::in|ios::binary, 0 );
6781+ auto file2 = get_file_idx (ios::in|ios::binary, 1 );
6782+ auto out = get_file_idx (ios::out|ios::binary, 2 );
6783+
6784+ out->seekp (0 , ios::beg);
6785+
6786+ unsigned int num_blocks = 0 ;
6787+ for (auto file : {file1, file2}) {
6788+ uf2_block block;
6789+ // Seek to 2nd block, in case 1st is abs_block
6790+ file->seekg (0 , ios::beg);
6791+ file->read ((char *)&block, sizeof (uf2_block));
6792+ if (file->fail ()) {
6793+ fail (ERROR_READ_FAILED, " unexpected end of input file" );
6794+ }
6795+
6796+ #if SUPPORT_RP2350_A2
6797+ if (check_abs_block (block)) {
6798+ // save abs block address
6799+ settings.uf2 .abs_block = true ;
6800+ settings.uf2 .abs_block_loc = block.target_addr ;
6801+ file->read ((char *)&block, sizeof (uf2_block));
6802+ }
6803+ #endif
6804+
6805+ num_blocks += block.num_blocks ;
6806+
6807+ if (!settings.family_id ) {
6808+ settings.family_id = block.file_size ;
6809+ }
6810+ }
6811+
6812+ #if SUPPORT_RP2350_A2
6813+ if (settings.uf2 .abs_block ) {
6814+ uf2_block block = gen_abs_block (settings.uf2 .abs_block_loc );
6815+ out->write ((char *)&block, sizeof (uf2_block));
6816+ }
6817+ #endif
6818+
6819+ unsigned int block_no = 0 ;
6820+ for (auto file : {file1, file2}) {
6821+ file->seekg (0 , ios::beg);
6822+ uf2_block block;
6823+ unsigned int pos = 0 ;
6824+ uint32_t next_family_id = 0 ;
6825+ do {
6826+ file->read ((char *)&block, sizeof (uf2_block));
6827+ if (file->fail ()) {
6828+ if (file->eof ()) { file->clear (); break ; }
6829+ fail (ERROR_READ_FAILED, " unexpected end of input file" );
6830+ }
6831+ if (block.magic_start0 == UF2_MAGIC_START0 && block.magic_start1 == UF2_MAGIC_START1 &&
6832+ block.magic_end == UF2_MAGIC_END) {
6833+ if (block.flags & UF2_FLAG_FAMILY_ID_PRESENT &&
6834+ !(block.flags & UF2_FLAG_NOT_MAIN_FLASH) && block.payload_size == PAGE_SIZE) {
6835+ // ignore the absolute block
6836+ if (check_abs_block (block)) {
6837+ DEBUG_LOG (" Ignoring RP2350-E10 absolute block\n " );
6838+ } else {
6839+ block.block_no = block_no; block_no++;
6840+ block.num_blocks = num_blocks;
6841+ block.file_size = settings.family_id ;
6842+ out->write ((char *)&block, sizeof (uf2_block));
6843+ }
6844+ }
6845+ }
6846+ pos += sizeof (uf2_block);
6847+ } while (true );
6848+ }
6849+
6850+ out->close ();
6851+
6852+ return false ;
6853+ }
6854+
67456855
67466856// Dissassembly helpers
67476857string gpiodir (int val) {
0 commit comments