1. Corgano

    OP Corgano Advanced Member
    Newcomer

    Joined:
    Jul 15, 2015
    Messages:
    56
    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.
     

    Attached Files:

    deejay87, f0li0, kickmeh and 3 others like this.
  2. RHOPKINS13

    RHOPKINS13 Geek
    Member

    Joined:
    Jan 31, 2009
    Messages:
    1,243
    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?
     
  3. Corgano

    OP Corgano Advanced Member
    Newcomer

    Joined:
    Jul 15, 2015
    Messages:
    56
    Country:
    Canada
    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, Jan 25, 2021
    uzimakiuchiha, redrum30 and iriez like this.
  4. iriez

    iriez GBAtemp Advanced Fan
    Member

    Joined:
    Oct 27, 2016
    Messages:
    545
    Country:
    United States
    Is there a hardware compatibility list? It's hard for me to believe this is universal to every single dongle?
     
  5. RHOPKINS13

    RHOPKINS13 Geek
    Member

    Joined:
    Jan 31, 2009
    Messages:
    1,243
    Country:
    United States
    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.
     
  6. Corgano

    OP Corgano Advanced Member
    Newcomer

    Joined:
    Jul 15, 2015
    Messages:
    56
    Country:
    Canada
    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, Jan 26, 2021
  7. Dust2dust

    Dust2dust GBAtemp Maniac
    Member

    Joined:
    Jun 17, 2010
    Messages:
    1,463
    Country:
    Canada
    It looks very useful. Always a drag to update the dongle payload. I'm happy to do it for one last time. Thanks for sharing!
     
    Corgano likes this.
  8. Holli12345

    Holli12345 Newbie
    Newcomer

    Joined:
    Aug 26, 2018
    Messages:
    7
    Country:
    Albania
    Can I put this in my dragoninjector too?
     
  9. Corgano

    OP Corgano Advanced Member
    Newcomer

    Joined:
    Jul 15, 2015
    Messages:
    56
    Country:
    Canada
    No, it isn't compressed. The dragon injector didn't have enough space for the full payload so its version is compressed when compiled
     
  10. BaamAlex

    BaamAlex CVE-2018-6242
    Member

    Joined:
    Jul 23, 2018
    Messages:
    3,299
    Country:
    Germany
    Can i use this with a trinket m0?
     
  11. Corgano

    OP Corgano Advanced Member
    Newcomer

    Joined:
    Jul 15, 2015
    Messages:
    56
    Country:
    Canada
    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.
     
  12. Draxzelex

    Draxzelex GBAtemp Legend
    Member

    Joined:
    Aug 6, 2017
    Messages:
    14,053
    Country:
    United States
    This is actually a very underrated payload. Good job OP.
     
    Dust2dust likes this.
Draft saved Draft deleted
Loading...

Hide similar threads Similar threads with keywords - Dragonboot, Atmosphere, generic