Hacking Dragonboot for Atmosphere / generic rcm tools

Corgano

Well-Known Member
OP
Newcomer
Joined
Jul 15, 2015
Messages
66
Trophies
0
Age
29
XP
521
Country
Canada
I made a modified version of dragonboot for atmosphere / generic RCM dongles. Dragonboot is a payload that loads a payload from SD card - so you'd never need to update the injector, just the SD card. I went one step further and changed the directory from \dragonboot\payload.bin to \atmosphere\reboot_payload.bin. This is the exact same as fusee-primary - however it comes in the atmosphere release and is always up to date. It also means if you have multiple switches running multiple versions of atmosphere (for some reason) the same payload will boot all of them. Completely version agnostic, as long as reboot_payload.bin is there.

TLDR: Put this on your dongle instead of fussee-primary, and you'll never need to update your dongle again

I made this for personal use but figured I'd share. Any recommendations or questions welcome.
 

Attachments

  • dragonboot_AMS_Universal.7z
    25.9 KB · Views: 461

RHOPKINS13

Geek
Member
Joined
Jan 31, 2009
Messages
1,353
Trophies
2
XP
2,614
Country
United States
Any source? Github link? Is this the same DragonBoot that was used with the DragonInjector? I used to have one of the test models.

Anyway, running random payloads on a Switch isn't really safe. Hate to be skeptical, but how do we know this is safe and trustworthy?
 
  • Angry
Reactions: PopcornSweetie

Corgano

Well-Known Member
OP
Newcomer
Joined
Jul 15, 2015
Messages
66
Trophies
0
Age
29
XP
521
Country
Canada
Any source? Github link? Is this the same DragonBoot that was used with the DragonInjector? I used to have one of the test models.

Anyway, running random payloads on a Switch isn't really safe. Hate to be skeptical, but how do we know this is safe and trustworthy?
Fair enough. The source is the dragonboot github. I don't know if it's still up, because they got C&D'd by nintendo and the project has been canceled. I only changed a few lines, and recompiled without compression. I basically told it that it was always in mode 0, and retirected that to the atmosphere folder, and had it look for reboot_payload.bin. Apart from that it's mostly unmodified. I could probably cut out a lot of the extraneous code but I couldn't be bothered.

Code:
/*
 * Copyright (c) 2018 Guillem96
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdarg.h>
#include <string.h>

#include "gfx/di.h"
#include "gfx/gfx.h"

#include "mem/heap.h"

#include "soc/hw_init.h"
#include "soc/t210.h"
#include "soc/pmc.h"

#include "core/launcher.h"

#include "utils/util.h"
#include "utils/fs_utils.h"
#include "utils/btn.h"

#define CENTERED_TEXT_START(n) (((1280 - n * CHAR_WIDTH * g_gfx_con.scale) / 2))

extern void pivot_stack(u32 stack_top);
extern u8 get_payload_num(void);

bool g_render_embedded_splash = true;

static inline void setup_gfx()
{
    u32 *fb = display_init_framebuffer();
    gfx_init_ctxt(&g_gfx_ctxt, fb, 1280, 720, 720);
    gfx_clear_color(&g_gfx_ctxt, 0xFF000000);
    gfx_con_init(&g_gfx_con, &g_gfx_ctxt);
    g_gfx_con.scale = 1;
}

void display_logo_with_message(int count, ...)
{
    /* vardiac arg list for multiple strings. */
    va_list strs;
    va_start(strs, count);

    /* save the scale factor so we can restore it later. */
    u8 scale_old = g_gfx_con.scale;

    if(g_render_embedded_splash)
    {
        /* set scale and position for logo */
        g_gfx_con.scale = 3;
        g_gfx_con.x = 370;
        g_gfx_con.y = 98;

        /* print logo.                                     */
        /* Logo chars are stored as part of the font,      */
        /* outside of normal ascii range.                  */
        /* The logo is comprised of 4 rows and 12 columns. */
        for(char i = 0; i < 4; i++)
        {
            for(char j = 0; j < 12; j++)
            {
                gfx_putc(&g_gfx_con, (i * 12) + j + 0x7F);
            }
            gfx_putc(&g_gfx_con, '\n');
            g_gfx_con.x = 370;
        }
    }

    /* set scale and y position for text. */
    g_gfx_con.scale = 1;
    g_gfx_con.y = 593;

    /* Allocate space for pointers to each string,                   */
    /* along with var to hold total number of chars to print         */
    /* and starting index to keep track of already processed strings */
    char **str_ptrs = malloc(count * sizeof(char *));
    int start = 0;
    int total_len = 0;
    for(int i = 0; i <= count; i++)
    {
        /* Get next string from va list */
        char *str = va_arg(strs, char *);
        str_ptrs[i] = str;

        /* Handle newlines separately, so text centering isn't thrown off, */
        /* and print characters that haven't been printed yet.             */
        if(str[0] == '\n' || i == count)
        {
            /* Set text position. Center text horizontally. */
            g_gfx_con.x = CENTERED_TEXT_START(total_len);

            /* Print each string, starting at calculated x position. */
            for(int j = start; j < i; j++)
                gfx_puts(&g_gfx_con, str_ptrs[j]);

            /* Next string to worry about is after current string.        */
            /* Reset number of characters to print to zero for next line. */
            start = i + 1;
            total_len = 0;

            gfx_putc(&g_gfx_con, '\n');
            continue;
        }

        total_len += strlen(str);
    }
    /* Free list of pointers. */
    free(str_ptrs);
    str_ptrs = 0;

    /* Restore the scale factor. */
    g_gfx_con.scale = scale_old;
}

void find_and_launch_payload(const char *folder)
{
    DIR dir;
    FILINFO finfo;
    //~ FRESULT res = f_findfirst(&dir, &finfo, folder, "*.bin");
    FRESULT res = f_findfirst(&dir, &finfo, folder, "reboot_payload.bin");
    if(res == FR_OK && (strlen(finfo.fname) != 0))
    {
        size_t path_size = strlen(finfo.fname) + strlen(folder) + 2;
        char *payload_path = malloc(path_size);
        if(payload_path != NULL)
        {
            memset(payload_path, 0, path_size);
            strcpy(payload_path, folder);
            strcat(payload_path, "/");
            strcat(payload_path, finfo.fname);
            if(g_render_embedded_splash)
                display_logo_with_message(2, "Launching ", payload_path);
            msleep(5000);
            launch_payload(payload_path);
        }
    }
    else if((strlen(finfo.fname) == 0) && (res != FR_NO_PATH))
    {
        g_gfx_con.fgcol = 0xFFFF0000;
        display_logo_with_message(5, "No payload found in ", folder, "!", "\n", "Press any button to reboot into RCM.");
    }
    else if(res == FR_NO_PATH)
    {
        g_gfx_con.fgcol = 0xFFFF0000;
        display_logo_with_message(7, "Folder not found!", "\n", "Please create ", folder, " on your SD card and add your payload to it.", "\n", "Press any button to reboot into RCM.");
    }
}

void ipl_main()
{
    config_hw();

    /* Init the stack and the heap */
    pivot_stack(0x90010000);
    heap_init(0x90020000);

    /* Init display and gfx module */
    display_init();
    setup_gfx();
    display_backlight_pwm_init();
    display_backlight_brightness(100, 1000);

    //~ u8 payload_num = get_payload_num() + 1;
    u8 payload_num = 0;

    if(sd_mount())
    {
        if(sd_file_read("dragonboot/splash.raw", g_gfx_ctxt.next))
        {
            g_render_embedded_splash = false;
            gfx_swap_buffer(&g_gfx_ctxt);
        }

        if(payload_num == 0)
            find_and_launch_payload("atmosphere");

        char folder[] = "dragonboot/\0\0\0";

        const char *num_table[] = { "00", "01", "02", "03", "04", "05", "06", "07", "08" };
        strcat(folder, num_table[payload_num]);

        find_and_launch_payload(folder);
    }
    else
    {
        g_gfx_con.fgcol = 0xFFFF0000;
        display_logo_with_message(3, "SD card not inserted!", "\n", "Press any button to reboot into RCM.");
    }

    btn_wait();
    PMC(APBDEV_PMC_SCRATCH0) |= 2;
    PMC(APBDEV_PMC_CNTRL) = PMC_CNTRL_MAIN_RST;
    while(1);
}
 
Last edited by Corgano,

RHOPKINS13

Geek
Member
Joined
Jan 31, 2009
Messages
1,353
Trophies
2
XP
2,614
Country
United States
Is there a hardware compatibility list? It's hard for me to believe this is universal to every single dongle?

It's universal to every single dongle the same way that Atmosphere, SX OS, Hekate, and any other payload is. The dongle itself isn't running the code, the Switch is. This is a "mini-payload" that's sole purpose is to boot a different payload (atmosphere/reboot_payload.bin) from the microSD card.
 

Corgano

Well-Known Member
OP
Newcomer
Joined
Jul 15, 2015
Messages
66
Trophies
0
Age
29
XP
521
Country
Canada
Is there a hardware compatibility list? It's hard for me to believe this is universal to every single dongle?
It's universal to rcm injectors in the sense that rcm injectors are designed to inject payloads. This is just a payload.

In contrast the original dragonboot was specific to an injector that supports the compression used - the dragon injector. Technically any rcm injector that can understand compressed payloads could inject dragonboot stock payload.
 
Last edited by Corgano,

Corgano

Well-Known Member
OP
Newcomer
Joined
Jul 15, 2015
Messages
66
Trophies
0
Age
29
XP
521
Country
Canada
Can i use this with a trinket m0?
That's a great question. IDK

Basically any standard payload injector with enough space to hold the payload can inject it and it;ll work. IF it works with the standard fusee primary payload it will probably work. Give us a try and let us know.
 

lordelan

Well-Known Member
Member
Joined
Jan 4, 2015
Messages
5,784
Trophies
1
Age
44
XP
6,505
Country
Germany
Argon NX does a very similar thing by always chainloading a payload that is named:
sd:\argon\payload.bin
If it doesn't exist, Argon looks for other payloads in a subfolder and shows them in a nice grid like hekate's NYX later did too.

However, I like the idea that it's directly booting the reboot payload in the atmosphere folder.

For those using hekate (like me) I wonder if the All-in-One Updater is putting the hekate payload there if I'm updating Atmosphère and hekate through it. Does anybody know?
 

Draxzelex

Well-Known Member
Member
Joined
Aug 6, 2017
Messages
19,005
Trophies
2
Age
29
Location
New York City
XP
13,369
Country
United States
Argon NX does a very similar thing by always chainloading a payload that is named:
sd:\argon\payload.bin
If it doesn't exist, Argon looks for other payloads in a subfolder and shows them in a nice grid like hekate's NYX later did too.

However, I like the idea that it's directly booting the reboot payload in the atmosphere folder.

For those using hekate (like me) I wonder if the All-in-One Updater is putting the hekate payload there if I'm updating Atmosphère and hekate through it. Does anybody know?
I think it does since Hekate is by far the best bootloader.
 
  • Like
Reactions: lordelan

DocKlokMan

Plugin Dev
Member
Joined
Apr 20, 2007
Messages
3,008
Trophies
2
Age
36
XP
4,569
Country
United States
Can I put this in my dragoninjector too?
You can now! I've taken the same approach as @Corgano and slim lined the payload. It simply boots sd:/atmosphere/reboot_payload.bin directly, I removed the splash screen and reduced the wait. Attached is a zip that contains both the BIN for use with other loaders as well as the UF2 file for those with actual DragonInjectors. Simply plug your DragonInjector into your computer and drag and drop the UF2 file into the drive that appears. The drive will disappear and re-appear again when the flashing is done. If you'd like to go back to original DragonInjector firmware you can download it here: https://github.com/jeromedontdev/DragonInjector-FW/releases/tag/DI_FW_1.00
 

Attachments

  • dragonboot_AMS_Universal-Mini.zip
    69.7 KB · Views: 237

Corgano

Well-Known Member
OP
Newcomer
Joined
Jul 15, 2015
Messages
66
Trophies
0
Age
29
XP
521
Country
Canada
Just an update to this. with the recent atmosphere 1.0.0 and newer releases fusee_primary no longer exists.

However this still just works perfectly. I havn't updated my dongle (or tegra RCM tool default on my pc, rekado automatic injecting payload) in over a year. It just fucking works.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    Sonic Angel Knight @ Sonic Angel Knight: :ninja: