Initial commit
[savezelda.git] / loader / main.c
1 // Copyright 2008-2009  Segher Boessenkool  <segher@kernel.crashing.org>
2 // This code is licensed to you under the terms of the GNU GPL, version 2;
3 // see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
4
5 #include "loader.h"
6
7
8 u8 *code_buffer = (u8 *)0x90100000;
9 u8 *trampoline_buffer = (u8 *)0x80001800;
10
11 static void dsp_reset(void)
12 {
13         write16(0x0c00500a, read16(0x0c00500a) & ~0x01f8);
14         write16(0x0c00500a, read16(0x0c00500a) | 0x0010);
15         write16(0x0c005036, 0);
16 }
17
18 static u32 reboot_trampoline[] = {
19         0x3c209000, // lis 1,0x9000
20         0x60210020, // ori 1,1,0x0020
21         0x7c2903a6, // mtctr 1
22         0x4e800420  // bctr
23 };
24
25 int try_sd_load(void)
26 {
27         int err;
28
29         err = sd_init();
30         if (err) {
31                 printf("SD card not found (%d)\n", err);
32                 return err;
33         }
34
35         err = fat_init();
36         if (err == 0)
37                 printf("SD card detected\n");
38         else {
39                 printf("SD card not detected (%d)\n", err);
40                 return err;
41         }
42
43 //      if (usbgecko_checkgecko())
44 //              printf("USBGecko serial interface detected\n");
45 //      else
46 //              printf("USBGecko serial interface not detected\n");
47
48         printf("Opening boot.elf:\n");
49         err = fat_open("boot.elf");
50
51         if (err) {
52                 printf("boot.elf not found (%d)\n", err);
53                 return err;
54         }
55
56 extern u32 fat_file_size;
57
58         printf("reading %d bytes...\n", fat_file_size);
59         err = fat_read(code_buffer, fat_file_size);
60         if (err) {
61                 printf("Error %d reading file\n", err);
62                 return err;
63         }
64
65         printf("Done.\n");
66         return 0;
67 }
68
69 int try_usbgecko_load(void)
70 {
71         if (!usbgecko_checkgecko()) {
72                 printf("USBGecko not found\n");
73                 return -1;
74         }
75
76 #define FLASH_OFFSET 0x30000
77         int i, size = usbgecko_flash_read32(FLASH_OFFSET);
78         if (size < 0) {
79                 printf("Invalid code size in usbgecko flash (%d)\n", size);
80                 return -1;
81         }
82         printf("Loading %d bytes from USBGecko flash (offset=%x)\n",
83                 size, FLASH_OFFSET+4);
84
85         for (i=0; i < size; i++)
86                 code_buffer[i] = usbgecko_flash_read8(FLASH_OFFSET + 4 + i);
87
88         return 0;
89 }
90
91 int main(void)
92 {
93         dsp_reset();
94
95         exception_init();
96
97         // Install trampoline at 80001800; some payloads like to jump
98         // there to restart.  Sometimes this can even work.
99         memcpy(trampoline_buffer, reboot_trampoline, sizeof(reboot_trampoline));
100
101         // Clear interrupt mask.
102         write32(0x0c003004, 0);
103
104         // Unlock EXI.
105         write32(0x0d00643c, 0);
106
107         video_init();
108         usbgecko_init();
109
110         printf("Twilight Hack %s\n", version);
111         printf("\n");
112         printf("Copyright 2008,2009  Segher Boessenkool\n");
113         printf("Copyright 2008  Haxx Enterprises\n");
114         printf("Copyright 2008  Hector Martin (\"marcan\")\n");
115         printf("Copyright 2003,2004  Felix Domke\n");
116         printf("\n");
117         printf("This code is licensed to you under the terms of the\n");
118         printf("GNU GPL, version 2; see the file COPYING\n");
119         printf("\n");
120         printf("Font and graphics by Freddy Leitner\n");
121         printf("\n");
122         printf("\n");
123
124         printf("Cleaning up environment... ");
125
126         reset_ios();
127
128         printf("OK.\n");
129
130
131         int err;
132
133  restart:
134         err = try_sd_load();
135
136         if (err) {
137                 err = try_usbgecko_load();
138
139                 if (err) {
140                         printf("No code found to load, hanging.\n");
141                         for (;;)
142                                 ;
143                 }
144         }
145
146         if (valid_elf_image(code_buffer)) {
147                 printf("Valid ELF image detected.\n");
148                 void (*entry)() = load_elf_image(code_buffer);
149                 entry();
150                 printf("Program returned to loader, reloading.\n");
151         } else
152                 printf("No valid ELF image detected, retrying.\n");
153
154         goto restart;
155 }