Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2006 by Barry Wardell |
| 11 | * |
| 12 | * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing |
| 13 | * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach |
| 14 | * |
| 15 | * All files in this archive are subject to the GNU General Public License. |
| 16 | * See the file COPYING in the source tree root for full license agreement. |
| 17 | * |
| 18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 19 | * KIND, either express or implied. |
| 20 | * |
| 21 | ****************************************************************************/ |
| 22 | #include "config.h" |
| 23 | |
| 24 | #include <stdlib.h> |
| 25 | #include <stdio.h> |
| 26 | #include <string.h> |
| 27 | #include "cpu.h" |
| 28 | #include "system.h" |
| 29 | #include "lcd.h" |
| 30 | #include "kernel.h" |
| 31 | #include "thread.h" |
| 32 | #include "ata.h" |
| 33 | #include "fat.h" |
| 34 | #include "disk.h" |
| 35 | #include "font.h" |
| 36 | #include "adc.h" |
| 37 | #include "backlight.h" |
| 38 | #include "button.h" |
| 39 | #include "panic.h" |
| 40 | #include "power.h" |
| 41 | #include "file.h" |
| 42 | |
| 43 | /* Size of the buffer to store the loaded Rockbox/iriver image */ |
| 44 | #define MAX_LOADSIZE (5*1024*1024) |
| 45 | |
| 46 | /* This is identical to the function used in the iPod bootloader */ |
| 47 | static void memmove16(void *dest, const void *src, unsigned count) |
| 48 | { |
| 49 | struct bufstr { |
| 50 | unsigned _buf[4]; |
| 51 | } *d, *s; |
| 52 | |
| 53 | if (src >= dest) { |
| 54 | count = (count + 15) >> 4; |
| 55 | d = (struct bufstr *) dest; |
| 56 | s = (struct bufstr *) src; |
| 57 | while (count--) |
| 58 | *d++ = *s++; |
| 59 | } else { |
| 60 | count = (count + 15) >> 4; |
| 61 | d = (struct bufstr *)(dest + (count <<4)); |
| 62 | s = (struct bufstr *)(src + (count <<4)); |
| 63 | while (count--) |
| 64 | *--d = *--s; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 69 | /* Load original iriver firmware. This function expects a file called |
| 70 | "H10_20GC.mi4" in the root directory of the player. It should be decrypted |
| 71 | and have the header stripped using mi4code. It reads the file in to a memory |
| 72 | buffer called buf. The rest of the loading is done in main() |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 73 | */ |
| 74 | int load_iriver(unsigned char* buf) |
| 75 | { |
| 76 | int fd; |
| 77 | int rc; |
| 78 | int len; |
| 79 | |
| 80 | fd = open("/H10_20GC.mi4", O_RDONLY); |
| 81 | |
| 82 | len = filesize(fd); |
| 83 | rc = read(fd, buf, len); |
| 84 | if(rc < len) |
| 85 | return -4; |
| 86 | |
| 87 | close(fd); |
| 88 | return len; |
| 89 | } |
| 90 | |
| 91 | /* A buffer to load the iriver firmware or Rockbox into */ |
| 92 | unsigned char loadbuffer[MAX_LOADSIZE]; |
| 93 | |
| 94 | void main(void) |
| 95 | { |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 96 | /* Attempt to load original iriver firmware. Successfully starts loading the |
| 97 | iriver firmware but then locks up once the "System Initialising" screen |
| 98 | is displayed. |
| 99 | |
| 100 | The iriver firmware was decrypted and the header removed. It was then |
| 101 | appended to the end of bootloader.bin and an mi4 file was created from |
| 102 | the resulting file. |
| 103 | |
| 104 | The original firmware starts at 0xd800 in the file and is of length |
| 105 | 0x47da00. |
| 106 | |
| 107 | The whole file (bootloader.bin + decrypted mi4) are loaded to memory by |
| 108 | the original iriver bootloader on startup. This copies the mi4 part to |
| 109 | the start of DRAM and passes execution to there. |
| 110 | |
| 111 | memmove16((void*)DRAMORIG, (void*)(DRAMORIG + 0xd800), 0x47da00); |
| 112 | asm volatile( |
| 113 | "mov r0, #" SC(DRAMORIG) "\n" |
| 114 | "mov pc, r0 \n" |
| 115 | ); |
| 116 | */ |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 117 | |
| 118 | int i; |
| 119 | int rc; |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 120 | int btn; |
| 121 | int fd; |
| 122 | char buffer[24]; |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 123 | |
| 124 | i=ata_init(); |
| 125 | disk_init(); |
| 126 | rc = disk_mount_all(); |
| 127 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 128 | /* Load original iriver firmware. Uses load_iriver(buf) to load the |
| 129 | decrypted mi4 file from disk to DRAM. This then copies that part of DRAM |
| 130 | to the start of DRAM and passes |
| 131 | execution to there. |
| 132 | |
| 133 | rc=load_iriver(loadbuffer); |
| 134 | memcpy((void*)DRAMORIG,loadbuffer,rc); |
| 135 | asm volatile( |
| 136 | "mov r0, #" SC(DRAMORIG) "\n" |
| 137 | "mov pc, r0 \n" |
| 138 | );*/ |
| 139 | |
| 140 | |
| 141 | /* This assumes that /test.txt exists */ |
| 142 | fd=open("/test.txt",O_RDWR); |
| 143 | |
| 144 | |
| 145 | /* |
| 146 | for(i=0;i<100;i++){ |
| 147 | btn = button_read_device(); |
| 148 | switch(btn){ |
| 149 | case BUTTON_LEFT: |
| 150 | snprintf(buffer, sizeof(buffer), "Left"); |
| 151 | write(fd,buffer,sizeof(buffer)); |
| 152 | break; |
| 153 | case BUTTON_RIGHT: |
| 154 | break; |
| 155 | case BUTTON_REW: |
| 156 | break; |
| 157 | case BUTTON_FF: |
| 158 | break; |
| 159 | case BUTTON_PLAY: |
| 160 | break; |
| 161 | default: |
| 162 | break; |
| 163 | } |
| 164 | |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 165 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 166 | } |
| 167 | */ |
| 168 | |
| 169 | |
| 170 | |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 171 | /* Investigate gpio |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 172 | |
| 173 | unsigned int gpio_a, gpio_b, gpio_c, gpio_d; |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 174 | unsigned int gpio_e, gpio_f, gpio_g, gpio_h; |
| 175 | unsigned int gpio_i, gpio_j, gpio_k, gpio_l; |
| 176 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 177 | gpio_a = GPIOA_INPUT_VAL; |
| 178 | gpio_b = GPIOB_INPUT_VAL; |
| 179 | gpio_c = GPIOC_INPUT_VAL; |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 180 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 181 | gpio_g = GPIOG_INPUT_VAL; |
| 182 | gpio_h = GPIOH_INPUT_VAL; |
| 183 | gpio_i = GPIOI_INPUT_VAL; |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 184 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 185 | snprintf(buffer,sizeof(buffer),"GPIO_A: %02x GPIO_G: %02x\n",gpio_a,gpio_g); |
| 186 | write(fd,buffer,sizeof(buffer)); |
| 187 | snprintf(buffer,sizeof(buffer),"GPIO_B: %02x GPIO_H: %02x\n",gpio_b,gpio_h); |
| 188 | write(fd,buffer,sizeof(buffer)); |
| 189 | snprintf(buffer,sizeof(buffer),"GPIO_C: %02x GPIO_I: %02x\n",gpio_c,gpio_i); |
| 190 | write(fd,buffer,sizeof(buffer)); |
| 191 | |
| 192 | gpio_d = GPIOD_INPUT_VAL; |
| 193 | gpio_e = GPIOE_INPUT_VAL; |
| 194 | gpio_f = GPIOF_INPUT_VAL; |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 195 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 196 | gpio_j = GPIOJ_INPUT_VAL; |
| 197 | gpio_k = GPIOK_INPUT_VAL; |
| 198 | gpio_l = GPIOL_INPUT_VAL; |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 199 | |
Hristo Kovachev | 1204136 | 2006-08-11 09:51:04 +0000 | [diff] [blame^] | 200 | snprintf(buffer,sizeof(buffer),"GPIO_D: %02x GPIO_J: %02x\n",gpio_d,gpio_j); |
| 201 | write(fd,buffer,sizeof(buffer)); |
| 202 | snprintf(buffer,sizeof(buffer),"GPIO_E: %02x GPIO_K: %02x\n",gpio_e,gpio_k); |
| 203 | write(fd,buffer,sizeof(buffer)); |
| 204 | snprintf(buffer,sizeof(buffer),"GPIO_F: %02x GPIO_L: %02x\n",gpio_f,gpio_l); |
| 205 | write(fd,buffer,sizeof(buffer)); |
| 206 | */ |
| 207 | |
| 208 | |
| 209 | |
| 210 | /* Detect the scroller being touched |
| 211 | |
| 212 | int j = 0; |
| 213 | for(j=0;j<1000;j++){ |
| 214 | if(gpio_c!=0xF7){ |
| 215 | snprintf(buffer, sizeof(buffer), "GPIO_C: %02x\n", gpio_c); |
| 216 | write(fd,buffer,sizeof(buffer)); |
| 217 | } |
| 218 | if(gpio_d!=0xDD){ |
| 219 | snprintf(buffer, sizeof(buffer), "GPIO_D: %02x\n", gpio_d); |
| 220 | write(fd,buffer,sizeof(buffer)); |
| 221 | } |
| 222 | }*/ |
| 223 | |
| 224 | |
| 225 | /* Apparently necessary for the data to be actually written to file */ |
| 226 | fsync(fd); |
| 227 | udelay(1000000); |
| 228 | |
| 229 | /* This causes the device to shut off instantly |
| 230 | |
| 231 | GPIOF_OUTPUT_VAL = 0; |
| 232 | */ |
| 233 | |
| 234 | close(fd); |
| 235 | udelay(1000000); |
Hristo Kovachev | 9dc0e62 | 2006-08-11 08:35:27 +0000 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | /* These functions are present in the firmware library, but we reimplement |
| 239 | them here because the originals do a lot more than we want */ |
| 240 | |
| 241 | void reset_poweroff_timer(void) |
| 242 | { |
| 243 | } |
| 244 | |
| 245 | int dbg_ports(void) |
| 246 | { |
| 247 | return 0; |
| 248 | } |
| 249 | |
| 250 | void mpeg_stop(void) |
| 251 | { |
| 252 | } |
| 253 | |
| 254 | void usb_acknowledge(void) |
| 255 | { |
| 256 | } |
| 257 | |
| 258 | void usb_wait_for_disconnect(void) |
| 259 | { |
| 260 | } |
| 261 | |
| 262 | void sys_poweroff(void) |
| 263 | { |
| 264 | } |