blob: 3938f819b4dcd4413cab6830652a6874d2cb7904 [file] [log] [blame]
Dave Chapmanda8bff12008-10-12 16:46:01 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
Dave Chapman08c41d42008-10-19 14:11:01 +00008 * $Id$
Dave Chapmanda8bff12008-10-12 16:46:01 +00009 *
10 * Copyright (C) 2008 by Rafaël Carré
11 *
12 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
13 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include <stdio.h>
26#include <system.h>
27#include <inttypes.h>
Dave Chapmanda8bff12008-10-12 16:46:01 +000028#include "config.h"
Thomas Martitz0e2286f2010-08-12 13:38:25 +000029#include "gcc_extensions.h"
Michael Sevakis4ea4cdf2014-08-08 02:28:11 -040030#include "../kernel-internal.h"
Dave Chapman8df1a7e2008-10-29 01:42:03 +000031#include "lcd.h"
Amaury Pouly761e7982015-01-08 22:30:22 +010032#ifdef HAVE_BOOTLOADER_USB_MODE
Rafaël Carréb8124652010-06-18 01:47:39 +000033#include "usb.h"
Rafaël Carréb8124652010-06-18 01:47:39 +000034#include "sysfont.h"
Amaury Pouly761e7982015-01-08 22:30:22 +010035#endif /* HAVE_BOOTLOADER_USB_MODE */
Rafaël Carré3520d8e2009-06-17 19:55:27 +000036#include "backlight.h"
Jonathan Gordonce505b82008-11-11 11:01:55 +000037#include "button-target.h"
Dave Chapman8df1a7e2008-10-29 01:42:03 +000038#include "common.h"
Marcin Bukat0b296912012-03-04 15:34:29 +010039#include "rb-loader.h"
40#include "loader_strerror.h"
Frank Gevaerts2f8a0082008-11-01 16:14:28 +000041#include "storage.h"
Michael Sevakis7d1a47c2013-08-05 22:02:45 -040042#include "file_internal.h"
Rafaël Carréaef27e12008-11-09 06:17:21 +000043#include "disk.h"
44#include "panic.h"
Mustapha Senhajiaeddacb2009-04-10 22:18:02 +000045#include "power.h"
Dave Chapmanda8bff12008-10-12 16:46:01 +000046
Bertrik Sikken7e3a3f42011-09-08 18:31:15 +000047void show_logo(void);
Rafaël Carréf5041532009-06-08 23:05:33 +000048
Amaury Pouly761e7982015-01-08 22:30:22 +010049#ifdef HAVE_BOOTLOADER_USB_MODE
Rafaël Carré1ec82122010-06-23 05:08:36 +000050static void usb_mode(void)
51{
52 if(usb_detect() != USB_INSERTED)
53 {
Rafaël Carré8c954e22011-07-02 02:49:20 +000054 static const char msg[] = "Plug USB cable";
Rafaël Carré1ec82122010-06-23 05:08:36 +000055 reset_screen();
56 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * sizeof(msg))) / 2,
57 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
58 lcd_update();
59
60 /* wait until USB is plugged */
61 while(usb_detect() != USB_INSERTED) ;
62 }
63
Rafaël Carré8c954e22011-07-02 02:49:20 +000064 static const char msg[] = "Bootloader USB mode";
Rafaël Carré1ec82122010-06-23 05:08:36 +000065 reset_screen();
66 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * sizeof(msg))) / 2,
67 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
68 lcd_update();
69
70 while(usb_detect() == USB_INSERTED)
71 sleep(HZ);
72
73 reset_screen();
74 lcd_update();
75}
Amaury Pouly761e7982015-01-08 22:30:22 +010076#endif /* HAVE_BOOTLOADER_USB_MODE */
Rafaël Carré1ec82122010-06-23 05:08:36 +000077
Thomas Martitz0e2286f2010-08-12 13:38:25 +000078void main(void) NORETURN_ATTR;
Dave Chapmanda8bff12008-10-12 16:46:01 +000079void main(void)
80{
Rafaël Carréaef27e12008-11-09 06:17:21 +000081 unsigned char* loadbuffer;
82 int buffer_size;
83 void(*kernel_entry)(void);
84 int ret;
Bertrik Sikken95726a52008-10-26 13:28:52 +000085
Rafaël Carréb3ee07c2008-10-28 11:24:29 +000086 system_init();
Rafaël Carré6e645cc2008-11-06 15:24:19 +000087 kernel_init();
Rafaël Carréb3ee07c2008-10-28 11:24:29 +000088
Rafaël Carré3520d8e2009-06-17 19:55:27 +000089 enable_irq();
90
Dave Chapman8df1a7e2008-10-29 01:42:03 +000091 lcd_init();
Dave Chapmanda8bff12008-10-12 16:46:01 +000092 show_logo();
93
Rafaël Carré3520d8e2009-06-17 19:55:27 +000094 backlight_init();
Dave Chapman8df1a7e2008-10-29 01:42:03 +000095
Rafaël Carré2b39cb42008-11-25 15:43:38 +000096 button_init_device();
Jonathan Gordonce505b82008-11-11 11:01:55 +000097 int btn = button_read_device();
98
Rafaël Carré12af2922010-02-05 12:40:25 +000099#if !defined(SANSA_FUZE) && !defined(SANSA_CLIP) && !defined(SANSA_CLIPV2) \
Bertrik Sikken463b3ed2011-08-27 16:21:19 +0000100 && !defined(SANSA_CLIPPLUS) && !defined(SANSA_CLIPZIP)
Mustapha Senhajiaeddacb2009-04-10 22:18:02 +0000101 if (button_hold())
102 {
103 verbose = true;
104 lcd_clear_display();
105 printf("Hold switch on");
106 printf("Shutting down...");
107 sleep(HZ);
108 power_off();
109 }
110#endif
111
Jonathan Gordonce505b82008-11-11 11:01:55 +0000112 /* Enable bootloader messages if any button is pressed */
113 if (btn)
Jonathan Gordonce505b82008-11-11 11:01:55 +0000114 {
115 lcd_clear_display();
116 verbose = true;
117 }
Rafaël Carréaef27e12008-11-09 06:17:21 +0000118
Rafaël Carréaef27e12008-11-09 06:17:21 +0000119 ret = storage_init();
120 if(ret < 0)
Rafaël Carré1ec82122010-06-23 05:08:36 +0000121 error(EATA, ret, true);
Rafaël Carréaef27e12008-11-09 06:17:21 +0000122
Michael Sevakis7d1a47c2013-08-05 22:02:45 -0400123 filesystem_init();
124
Amaury Pouly761e7982015-01-08 22:30:22 +0100125#ifdef HAVE_BOOTLOADER_USB_MODE
Rafaël Carréb8124652010-06-18 01:47:39 +0000126 usb_init();
Rafaël Carré1ec82122010-06-23 05:08:36 +0000127
128 /* Enter USB mode if USB is plugged and SELECT button is pressed */
Mihail Zenkov8b8b8542014-09-29 22:05:25 +0000129 if(btn & BUTTON_SELECT) {
130 usb_start_monitoring();
131 if(usb_detect() == USB_INSERTED)
132 usb_mode();
133 }
Amaury Pouly761e7982015-01-08 22:30:22 +0100134#endif /* HAVE_BOOTLOADER_USB_MODE */
Rafaël Carré1ec82122010-06-23 05:08:36 +0000135
Rafaël Carré1ec82122010-06-23 05:08:36 +0000136 while((ret = disk_mount_all()) <= 0)
Rafaël Carréb8124652010-06-18 01:47:39 +0000137 {
Amaury Pouly761e7982015-01-08 22:30:22 +0100138#ifdef HAVE_BOOTLOADER_USB_MODE
Rafaël Carré1ec82122010-06-23 05:08:36 +0000139 error(EDISK, ret, false);
Mihail Zenkov2ec6fbc2015-06-01 23:41:15 +0000140 usb_start_monitoring();
Rafaël Carré1ec82122010-06-23 05:08:36 +0000141 usb_mode();
Rafaël Carré64d3a222010-06-23 05:16:24 +0000142#else
143 error(EDISK, ret, true);
144#endif
Rafaël Carréb8124652010-06-18 01:47:39 +0000145 }
Rafaël Carréaef27e12008-11-09 06:17:21 +0000146
147 printf("Loading firmware");
148
Thomas Martitz46334462009-05-20 21:09:53 +0000149 loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */
150 buffer_size = (int)(loadbuffer + (DRAM_SIZE) - TTB_SIZE);
Rafaël Carréaef27e12008-11-09 06:17:21 +0000151
Marcin Bukat0b296912012-03-04 15:34:29 +0100152 while((ret = load_firmware(loadbuffer, BOOTFILE, buffer_size)) <= EFILE_EMPTY)
Rafaël Carréaef27e12008-11-09 06:17:21 +0000153 {
Amaury Pouly761e7982015-01-08 22:30:22 +0100154#ifdef HAVE_BOOTLOADER_USB_MODE
Rafaël Carré1ec82122010-06-23 05:08:36 +0000155 error(EBOOTFILE, ret, false);
Mihail Zenkov2ec6fbc2015-06-01 23:41:15 +0000156 usb_start_monitoring();
Rafaël Carré1ec82122010-06-23 05:08:36 +0000157 usb_mode();
Rafaël Carré64d3a222010-06-23 05:16:24 +0000158#else
159 error(EBOOTFILE, ret, true);
160#endif
Bertrik Sikken95726a52008-10-26 13:28:52 +0000161 }
Dave Chapmanda8bff12008-10-12 16:46:01 +0000162
Mihail Zenkov7cb1e5a2016-04-22 12:17:35 +0000163#if defined(SANSA_FUZEV2) || defined(SANSA_CLIPPLUS) || defined(SANSA_CLIPZIP)
164 /* It is necessary for proper detection AMSv2 variant 1.
165 * We should restore initial state of GPIOB_PIN(5) as it used for
166 * variant detection, but can be changed if we switch SD card. */
167 if (amsv2_variant == 1)
168 GPIOB_PIN(5) = 1 << 5;
169#endif
Rafaël Carré1ec82122010-06-23 05:08:36 +0000170 kernel_entry = (void*) loadbuffer;
Michael Sevakis09769822011-12-17 07:54:00 +0000171 commit_discard_idcache();
Rafaël Carré1ec82122010-06-23 05:08:36 +0000172 printf("Executing");
173 kernel_entry();
174 printf("ERR: Failed to boot");
175
Dave Chapmanda8bff12008-10-12 16:46:01 +0000176 /* never returns */
177 while(1) ;
178}