Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2006 by Greg White |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | #include "config.h" |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 22 | #include "system.h" |
Frank Gevaerts | ab4a162 | 2010-05-06 22:13:54 +0000 | [diff] [blame] | 23 | #include <stdio.h> |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 24 | #include <errno.h> |
Michael Sevakis | 4ea4cdf | 2014-08-08 02:28:11 -0400 | [diff] [blame] | 25 | #include "../kernel-internal.h" |
Thomas Martitz | 0e2286f | 2010-08-12 13:38:25 +0000 | [diff] [blame] | 26 | #include "gcc_extensions.h" |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 27 | #include "string.h" |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 28 | #include "adc.h" |
| 29 | #include "powermgmt.h" |
Frank Gevaerts | 2f8a008 | 2008-11-01 16:14:28 +0000 | [diff] [blame] | 30 | #include "storage.h" |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 31 | #include "file_internal.h" |
Nicolas Pennequin | c2ca8c7 | 2007-11-27 15:40:29 +0000 | [diff] [blame] | 32 | #include "dir.h" |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 33 | #include "file.h" |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 34 | #include "disk.h" |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 35 | #include "common.h" |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 36 | #include "rb-loader.h" |
| 37 | #include "loader_strerror.h" |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 38 | #include "power.h" |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 39 | #include "backlight.h" |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 40 | #include "usb.h" |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 41 | #include "button.h" |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 42 | #include "font.h" |
| 43 | #include "lcd.h" |
Rafaël Carré | 5d236b2 | 2010-05-27 09:41:46 +0000 | [diff] [blame] | 44 | #include "version.h" |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 45 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 46 | /* Show the Rockbox logo - in show_logo.c */ |
Bertrik Sikken | 7e3a3f4 | 2011-09-08 18:31:15 +0000 | [diff] [blame] | 47 | extern void show_logo(void); |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 48 | |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 49 | #define TAR_CHUNK 512 |
| 50 | #define TAR_HEADER_SIZE 157 |
| 51 | |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 52 | /* Where files sent via MTP are stored */ |
| 53 | static const char basedir[] = "/Content/0b00/00/"; |
| 54 | /* Can use memory after vector table up to 0x01f00000 */ |
| 55 | static char * const tarbuf = (char *)0x00000040; |
| 56 | static const size_t tarbuf_size = 0x01f00000 - 0x00000040; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 57 | /* Firmware data */ |
| 58 | static void * const load_buf = 0x00000000; |
| 59 | static const size_t load_buf_size = 0x20000000 - 0x100000; |
| 60 | static const void * const start_addr = 0x00000000; |
Michael Sevakis | a07c034 | 2008-02-08 02:20:05 +0000 | [diff] [blame] | 61 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 62 | /* Show a message + "Shutting down...", then power off the device */ |
| 63 | static void display_message_and_power_off(int timeout, const char *msg) |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 64 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 65 | verbose = true; |
| 66 | printf(msg); |
| 67 | printf("Shutting down..."); |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 68 | sleep(timeout); |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 69 | power_off(); |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 72 | static void check_battery_safe(void) |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 73 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 74 | if (battery_level_safe()) |
| 75 | return; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 76 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 77 | display_message_and_power_off(HZ, "Battery low"); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 78 | } |
| 79 | |
| 80 | /* TODO: Handle charging while connected */ |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 81 | static void handle_usb(int connect_timeout) |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 82 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 83 | long end_tick = 0; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 84 | int button; |
| 85 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 86 | /* We need full button and backlight handling now */ |
| 87 | backlight_init(); |
| 88 | button_init(); |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 89 | backlight_on(); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 90 | |
| 91 | /* Start the USB driver */ |
| 92 | usb_init(); |
| 93 | usb_start_monitoring(); |
| 94 | |
| 95 | /* Wait for threads to connect or cable is pulled */ |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 96 | printf("USB: Connecting"); |
| 97 | |
| 98 | if (connect_timeout != TIMEOUT_BLOCK) |
| 99 | end_tick = current_tick + connect_timeout; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 100 | |
| 101 | while (1) |
| 102 | { |
| 103 | button = button_get_w_tmo(HZ/2); |
| 104 | |
| 105 | if (button == SYS_USB_CONNECTED) |
| 106 | break; /* Hit */ |
| 107 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 108 | if (connect_timeout != TIMEOUT_BLOCK && |
| 109 | TIME_AFTER(current_tick, end_tick)) |
| 110 | { |
| 111 | /* Timed out waiting for the connect - will happen when connected |
| 112 | * to a charger through the USB port */ |
| 113 | printf("USB: Timed out"); |
| 114 | break; |
| 115 | } |
| 116 | |
Michael Sevakis | 36bc6a1 | 2012-01-01 03:19:52 +0000 | [diff] [blame] | 117 | if (usb_plugged() == USB_EXTRACTED) |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 118 | break; /* Cable pulled */ |
| 119 | } |
| 120 | |
| 121 | if (button == SYS_USB_CONNECTED) |
| 122 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 123 | /* Switch to verbose mode if not in it so that the status updates |
| 124 | * are shown */ |
| 125 | verbose = true; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 126 | /* Got the message - wait for disconnect */ |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 127 | printf("Bootloader USB mode"); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 128 | |
| 129 | usb_acknowledge(SYS_USB_CONNECTED_ACK); |
| 130 | |
| 131 | while (1) |
| 132 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 133 | button = button_get_w_tmo(HZ/2); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 134 | if (button == SYS_USB_DISCONNECTED) |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 135 | break; |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 136 | |
| 137 | check_battery_safe(); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 138 | } |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 139 | |
| 140 | backlight_on(); |
| 141 | /* Sleep a little to let the backlight ramp up */ |
| 142 | sleep(HZ*5/4); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 143 | } |
| 144 | |
| 145 | /* Put drivers initialized for USB connection into a known state */ |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 146 | usb_close(); |
| 147 | button_close(); |
| 148 | backlight_close(); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 149 | } |
| 150 | |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 151 | static void untar(int tar_fd) |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 152 | { |
| 153 | char header[TAR_HEADER_SIZE]; |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 154 | char *ptr; |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 155 | char path[102]; |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 156 | int fd, i; |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 157 | int ret; |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 158 | size_t size = filesize(tar_fd); |
| 159 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 160 | if (size > tarbuf_size) |
| 161 | { |
Michael Sevakis | c41caca | 2008-05-07 07:14:39 +0000 | [diff] [blame] | 162 | printf("tar file too large"); /* Paranoid but proper */ |
| 163 | return; |
| 164 | } |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 165 | |
| 166 | ret = read(tar_fd, tarbuf, filesize(tar_fd)); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 167 | if (ret < 0) |
| 168 | { |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 169 | printf("couldn't read tar file (%d)", ret); |
| 170 | return; |
| 171 | } |
| 172 | ptr = tarbuf; |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 173 | |
| 174 | while (1) |
| 175 | { |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 176 | memcpy(header, ptr, TAR_HEADER_SIZE); |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 177 | |
| 178 | if (*header == '\0') /* Check for EOF */ |
| 179 | break; |
| 180 | |
| 181 | /* Parse the size field */ |
| 182 | size = 0; |
| 183 | for (i = 124 ; i < 124 + 11 ; i++) { |
| 184 | size = (8 * size) + header[i] - '0'; |
| 185 | } |
| 186 | |
| 187 | /* Skip rest of header */ |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 188 | ptr += TAR_CHUNK; |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 189 | |
| 190 | /* Make the path absolute */ |
| 191 | strcpy(path, "/"); |
| 192 | strcat(path, header); |
| 193 | |
| 194 | if (header[156] == '0') /* file */ |
| 195 | { |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 196 | int wc; |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 197 | |
Thomas Martitz | c61e89c | 2010-05-06 17:35:04 +0000 | [diff] [blame] | 198 | fd = creat(path, 0666); |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 199 | if (fd < 0) |
| 200 | { |
| 201 | printf("failed to create file (%d)", fd); |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 202 | } |
| 203 | else |
| 204 | { |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 205 | wc = write(fd, ptr, size); |
| 206 | if (wc < 0) |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 207 | { |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 208 | printf("write failed (%d)", wc); |
| 209 | break; |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 210 | } |
| 211 | close(fd); |
| 212 | } |
Nicolas Pennequin | 90a3d58 | 2008-04-16 00:38:06 +0000 | [diff] [blame] | 213 | ptr += (size + TAR_CHUNK-1) & (~(TAR_CHUNK-1)); |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 214 | } |
| 215 | else if (header[156] == '5') /* directory */ |
| 216 | { |
| 217 | int ret; |
| 218 | |
| 219 | /* Remove the trailing slash */ |
| 220 | if (path[strlen(path) - 1] == '/') |
| 221 | path[strlen(path) - 1] = '\0'; |
| 222 | |
| 223 | /* Create the dir */ |
| 224 | ret = mkdir(path); |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 225 | if (ret < 0 && errno != EEXIST) |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 226 | { |
| 227 | printf("failed to create dir (%d)", ret); |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 233 | /* Look for a tar file or rockbox binary in the MTP directory */ |
| 234 | static void handle_untar(void) |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 235 | { |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 236 | char buf[MAX_PATH]; |
| 237 | char tarstring[6]; |
Nicolas Pennequin | 620e6b4 | 2008-04-15 23:17:03 +0000 | [diff] [blame] | 238 | char model[5]; |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 239 | struct dirent* entry; |
| 240 | DIR* dir; |
Nicolas Pennequin | c2ca8c7 | 2007-11-27 15:40:29 +0000 | [diff] [blame] | 241 | int fd; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 242 | int rc; |
| 243 | |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 244 | dir = opendir(basedir); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 245 | |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 246 | while ((entry = readdir(dir))) |
Nicolas Pennequin | c2ca8c7 | 2007-11-27 15:40:29 +0000 | [diff] [blame] | 247 | { |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 248 | if (*entry->d_name == '.') |
| 249 | continue; |
Nicolas Pennequin | 620e6b4 | 2008-04-15 23:17:03 +0000 | [diff] [blame] | 250 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 251 | snprintf(buf, sizeof(buf), "%s%s", basedir, entry->d_name); |
| 252 | fd = open(buf, O_RDONLY); |
| 253 | |
| 254 | if (fd < 0) |
| 255 | continue; |
| 256 | |
| 257 | /* Check whether the file is a rockbox binary. */ |
| 258 | lseek(fd, 4, SEEK_SET); |
| 259 | rc = read(fd, model, 4); |
| 260 | if (rc == 4) |
| 261 | { |
| 262 | model[4] = 0; |
| 263 | if (strcmp(model, "gigs") == 0) |
| 264 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 265 | verbose = true; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 266 | printf("Found rockbox binary. Moving..."); |
Nicolas Pennequin | e2f5f21 | 2008-02-17 23:17:08 +0000 | [diff] [blame] | 267 | close(fd); |
Björn Stenberg | b69be10 | 2008-11-23 22:07:48 +0000 | [diff] [blame] | 268 | int ret = rename(buf, BOOTDIR "/" BOOTFILE); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 269 | printf("returned %d", ret); |
| 270 | sleep(HZ); |
| 271 | break; |
Nicolas Pennequin | c2ca8c7 | 2007-11-27 15:40:29 +0000 | [diff] [blame] | 272 | } |
| 273 | } |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 274 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 275 | /* Check whether the file is a tar file. */ |
| 276 | lseek(fd, 257, SEEK_SET); |
| 277 | rc = read(fd, tarstring, 5); |
| 278 | if (rc == 5) |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 279 | { |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 280 | tarstring[5] = 0; |
| 281 | if (strcmp(tarstring, "ustar") == 0) |
| 282 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 283 | verbose = true; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 284 | printf("Found tar file. Unarchiving..."); |
| 285 | lseek(fd, 0, SEEK_SET); |
| 286 | untar(fd); |
| 287 | close(fd); |
| 288 | printf("Removing tar file"); |
| 289 | remove(buf); |
| 290 | break; |
| 291 | } |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 292 | } |
| 293 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 294 | close(fd); |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 295 | } |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 296 | } |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 297 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 298 | /* Try to load the firmware and run it */ |
Thomas Martitz | 0e2286f | 2010-08-12 13:38:25 +0000 | [diff] [blame] | 299 | static void NORETURN_ATTR handle_firmware_load(void) |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 300 | { |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 301 | int rc = load_firmware(load_buf, BOOTFILE, load_buf_size); |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 302 | |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 303 | if(rc <= EFILE_EMPTY) |
Rafaël Carré | 1ec8212 | 2010-06-23 05:08:36 +0000 | [diff] [blame] | 304 | error(EBOOTFILE, rc, true); |
Michael Sevakis | a07c034 | 2008-02-08 02:20:05 +0000 | [diff] [blame] | 305 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 306 | /* Pause to look at messages */ |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 307 | while (1) |
| 308 | { |
| 309 | int button = button_read_device(); |
| 310 | |
| 311 | /* Ignore settings reset */ |
| 312 | if (button == BUTTON_NONE || button == BUTTON_MENU) |
| 313 | break; |
| 314 | |
| 315 | sleep(HZ/5); |
| 316 | |
| 317 | check_battery_safe(); |
| 318 | |
| 319 | /* If the disk powers off, the firmware will lock at startup */ |
| 320 | storage_spin(); |
| 321 | } |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 322 | |
| 323 | /* Put drivers into a known state */ |
| 324 | button_close_device(); |
Frank Gevaerts | 2f8a008 | 2008-11-01 16:14:28 +0000 | [diff] [blame] | 325 | storage_close(); |
Michael Sevakis | a07c034 | 2008-02-08 02:20:05 +0000 | [diff] [blame] | 326 | system_prepare_fw_start(); |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 327 | |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 328 | commit_discard_idcache(); |
| 329 | asm volatile ("bx %0": : "r"(start_addr)); |
Nicolas Pennequin | c2ca8c7 | 2007-11-27 15:40:29 +0000 | [diff] [blame] | 330 | |
Michael Sevakis | 94f7d0f | 2008-04-18 16:42:50 +0000 | [diff] [blame] | 331 | /* Halt */ |
| 332 | while (1) |
| 333 | core_idle(); |
Will Robertson | 590501c | 2007-09-21 15:51:53 +0000 | [diff] [blame] | 334 | } |
| 335 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 336 | void main(void) |
| 337 | { |
| 338 | int rc; |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 339 | int batt; |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 340 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 341 | system_init(); |
| 342 | kernel_init(); |
| 343 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 344 | /* Keep button_device_init early to delay calls to button_read_device */ |
| 345 | button_init_device(); |
| 346 | |
| 347 | lcd_init(); |
| 348 | font_init(); |
| 349 | show_logo(); |
Michael Sevakis | 4d3a020 | 2009-02-07 10:09:13 +0000 | [diff] [blame] | 350 | lcd_clear_display(); |
| 351 | |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 352 | if (button_hold()) |
| 353 | display_message_and_power_off(HZ, "Hold switch on"); |
| 354 | |
| 355 | if (button_read_device() != BUTTON_NONE) |
| 356 | verbose = true; |
| 357 | |
Michael Sevakis | 4d3a020 | 2009-02-07 10:09:13 +0000 | [diff] [blame] | 358 | printf("Gigabeat S Rockbox Bootloader"); |
Michael Sevakis | 95a4c3a | 2014-08-28 10:26:45 -0400 | [diff] [blame] | 359 | printf("Version %s", rbversion); |
Michael Sevakis | 4d3a020 | 2009-02-07 10:09:13 +0000 | [diff] [blame] | 360 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 361 | adc_init(); |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 362 | batt = _battery_voltage(); |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 363 | printf("Battery: %d.%03d V", batt / 1000, batt % 1000); |
| 364 | check_battery_safe(); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 365 | |
Frank Gevaerts | 2f8a008 | 2008-11-01 16:14:28 +0000 | [diff] [blame] | 366 | rc = storage_init(); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 367 | if(rc) |
Rafaël Carré | 1ec8212 | 2010-06-23 05:08:36 +0000 | [diff] [blame] | 368 | error(EATA, rc, true); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 369 | |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 370 | filesystem_init(); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 371 | |
| 372 | rc = disk_mount_all(); |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 373 | if (rc <= 0) |
Rafaël Carré | 1ec8212 | 2010-06-23 05:08:36 +0000 | [diff] [blame] | 374 | error(EDISK, rc, true); |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 375 | |
| 376 | printf("Init complete"); |
| 377 | |
| 378 | /* Do USB first since a tar or binary could be added to the MTP directory |
| 379 | * at the time and we can untar or move after unplugging. */ |
Michael Sevakis | 36bc6a1 | 2012-01-01 03:19:52 +0000 | [diff] [blame] | 380 | if (usb_plugged() == USB_INSERTED) |
Michael Sevakis | 863c03f | 2011-01-21 07:05:51 +0000 | [diff] [blame] | 381 | handle_usb(HZ*2); |
| 382 | |
Michael Sevakis | 80278e4 | 2008-05-10 18:00:11 +0000 | [diff] [blame] | 383 | handle_untar(); |
| 384 | handle_firmware_load(); /* No return */ |
| 385 | } |