diff --git a/loader/source/firm.c b/loader/source/firm.c
new file mode 100644
index 00000000..c3368769
--- /dev/null
+++ b/loader/source/firm.c
@@ -0,0 +1,44 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2017 Aurora Wright, TuxSH
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that 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 .
+*
+* Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified
+* reasonable legal notices or author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+*/
+
+#include "firm.h"
+#include "memory.h"
+#include "cache.h"
+
+void launchFirm(Firm *firm, int argc, char **argv)
+{
+
+ //Copy FIRM sections to respective memory locations
+ for(u32 sectionNum = 0; sectionNum < 4 && firm->section[sectionNum].size != 0; sectionNum++)
+ memcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
+
+ //Set ARM11 entrypoint
+ *(vu32 *)0x1FFFFFFC = (u32)firm->arm11Entry;
+
+ //Ensure that all memory transfers have completed and that the caches have been flushed
+ flushCaches();
+
+ //Jump to ARM9 entrypoint. Also give it additional arguments it can dismiss
+ ((void (*)(int, char**, u32))firm->arm9Entry)(argc, argv, 0x0000BEEF);
+
+ __builtin_unreachable();
+}
diff --git a/loader/source/firm.h b/loader/source/firm.h
new file mode 100644
index 00000000..47dc7ba7
--- /dev/null
+++ b/loader/source/firm.h
@@ -0,0 +1,46 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2017 Aurora Wright, TuxSH
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that 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 .
+*
+* Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified
+* reasonable legal notices or author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+*/
+
+#pragma once
+
+#include "types.h"
+
+typedef struct __attribute__((packed))
+{
+ u32 offset;
+ u8 *address;
+ u32 size;
+ u32 procType;
+ u8 hash[0x20];
+} FirmSection;
+
+typedef struct __attribute__((packed))
+{
+ char magic[4];
+ u32 reserved1;
+ u8 *arm11Entry;
+ u8 *arm9Entry;
+ u8 reserved2[0x30];
+ FirmSection section[4];
+} Firm;
+
+void launchFirm(Firm *firm, int argc, char **argv);
diff --git a/source/start.s b/source/start.s
index 2a05828c..39dea1cf 100644
--- a/source/start.s
+++ b/source/start.s
@@ -33,6 +33,9 @@ _start:
cmp r2, r4
movne r0, #0 @ check magic word
+ mov r9, r0
+ mov r10, r1
+
@ Change the stack pointer
mov sp, #0x27000000
@@ -47,8 +50,6 @@ _start:
bl flushEntireDCache
bl flushEntireICache
- push {r0-r3}
-
@ Give read/write access to all the memory regions
ldr r0, =0x3333333
mcr p15, 0, r0, c5, c0, 2 @ write data access
@@ -97,5 +98,6 @@ _start:
sub r2, r0
bl memset32
- pop {r0-r3}
+ mov r0, r9
+ mov r1, r10
b main