Something went wrong. Try again.
A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
Something went wrong. Try again.
14 kB · 506 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2006 by Barry Wardell * * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach * * 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 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include <stdio.h>#include <stdlib.h>
#include "config.h"#include "common.h"#include "cpu.h"#include "file.h"#include "system.h"#include "../kernel-internal.h"#include "lcd.h"#include "font.h"#include "storage.h"#include "file_internal.h"#include "adc.h"#include "button.h"#include "disk.h"#include "crc32.h"#include "mi4-loader.h"#include "loader_strerror.h"#include <string.h>#include "power.h"#include "version.h"#if defined(SANSA_E200) || defined(PHILIPS_SA9200)#include "i2c.h"#include "backlight-target.h"#endif#include "usb.h"#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)#include "usb_drv.h"#endif#if defined(SANSA_E200) && defined(HAVE_BOOTLOADER_USB_MODE)#include "core_alloc.h"#endif#if defined(SAMSUNG_YH925)/* this function (in lcd-yh925.c) resets the screen orientation for the OF * for use with dualbooting */void lcd_reset(void);#endif
/* Button definitions */#if CONFIG_KEYPAD == IRIVER_H10_PAD#define BOOTLOADER_BOOT_OF BUTTON_LEFT
#elif CONFIG_KEYPAD == SANSA_E200_PAD#define BOOTLOADER_BOOT_OF BUTTON_LEFT
#elif CONFIG_KEYPAD == SANSA_C200_PAD#define BOOTLOADER_BOOT_OF BUTTON_LEFT
#elif CONFIG_KEYPAD == MROBE100_PAD#define BOOTLOADER_BOOT_OF BUTTON_POWER
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD#define BOOTLOADER_BOOT_OF BUTTON_VOL_UP
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD#define BOOTLOADER_BOOT_OF BUTTON_MENU
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD#define BOOTLOADER_BOOT_OF BUTTON_VOL_UP
#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)#define BOOTLOADER_BOOT_OF BUTTON_LEFT
#elif CONFIG_KEYPAD == SANSA_FUZE_PAD#define BOOTLOADER_BOOT_OF BUTTON_LEFT
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD#define BOOTLOADER_BOOT_OF BUTTON_OK
#endif
/* Maximum allowed firmware image size. 10MB is more than enough */#define MAX_LOADSIZE (10*1024*1024)
/* A buffer to load the original firmware or Rockbox into */unsigned char *loadbuffer = (unsigned char *)DRAM_START;
/* Locations and sizes in hidden partition on Sansa */#if (CONFIG_STORAGE & STORAGE_SD)#define PPMI_SECTOR_OFFSET 1024#define PPMI_SECTORS 1#define MI4_HEADER_SECTORS 1#define NUM_PARTITIONS 2
#else#define NUM_PARTITIONS 1
#endif
#define MI4_HEADER_SIZE 0x200
/* PPMI header structure */struct ppmi_header_t { unsigned char magic[4]; uint32_t length; uint32_t pad[126];};
#if (CONFIG_STORAGE & STORAGE_SD)/* Load mi4 firmware from a hidden disk partition */int load_mi4_part(unsigned char* buf, struct partinfo* pinfo, unsigned int buffer_size, bool disable_rebuild){ struct mi4header_t mi4header; struct ppmi_header_t ppmi_header; unsigned long sum;
/* Read header to find out how long the mi4 file is. */ storage_read_sectors(IF_MD(0,) pinfo->start + PPMI_SECTOR_OFFSET, PPMI_SECTORS, &ppmi_header);
/* The first four characters at 0x80000 (sector 1024) should be PPMI*/ if( memcmp(ppmi_header.magic, "PPMI", 4) ) return EFILE_NOT_FOUND;
printf("BL mi4 size: %x", ppmi_header.length);
/* Read mi4 header of the OF */ storage_read_sectors(IF_MD(0,) pinfo->start + PPMI_SECTOR_OFFSET + PPMI_SECTORS + (ppmi_header.length/512), MI4_HEADER_SECTORS, &mi4header);
/* We don't support encrypted mi4 files yet */ if( (mi4header.plaintext) != (mi4header.mi4size-MI4_HEADER_SIZE)) return EINVALID_FORMAT;
/* MI4 file size */ printf("OF mi4 size: %x", mi4header.mi4size);
if ((mi4header.mi4size-MI4_HEADER_SIZE) > buffer_size) return EFILE_TOO_BIG;
/* CRC32 */ printf("CRC32: %x", mi4header.crc32);
/* Rockbox model id */ printf("Model id: %.4s", mi4header.model);
/* Read binary type (RBOS, RBBL) */ printf("Binary type: %.4s", mi4header.type);
/* Load firmware */ storage_read_sectors(IF_MD(0,) pinfo->start + PPMI_SECTOR_OFFSET + PPMI_SECTORS + (ppmi_header.length/512) + MI4_HEADER_SECTORS, (mi4header.mi4size-MI4_HEADER_SIZE)/512, buf);
/* Check CRC32 to see if we have a valid file */ sum = crc_32r (buf,mi4header.mi4size-MI4_HEADER_SIZE,0);
printf("Calculated CRC32: %x", sum);
if(sum != mi4header.crc32) return EBAD_CHKSUM;
#ifdef SANSA_E200 if (disable_rebuild) { char block[512];
printf("Disabling database rebuild");
storage_read_sectors(IF_MD(0,) pinfo->start + 0x3c08, 1, block); block[0xe1] = 0; storage_write_sectors(IF_MD(0,) pinfo->start + 0x3c08, 1, block); }#else (void) disable_rebuild;#endif
return mi4header.mi4size-MI4_HEADER_SIZE;}#endif /* (CONFIG_STORAGE & STORAGE_SD) */
#ifdef HAVE_BOOTLOADER_USB_MODE/* Return USB_HANDLED if session took place else return USB_EXTRACTED */static int handle_usb(int connect_timeout){ static struct event_queue q SHAREDBSS_ATTR; struct queue_event ev; int usb = USB_EXTRACTED; long end_tick = 0;
if (!usb_plugged()) return USB_EXTRACTED;
queue_init(&q, true); usb_init(); usb_start_monitoring();
printf("USB: Connecting");
if (connect_timeout != TIMEOUT_BLOCK) end_tick = current_tick + connect_timeout;
while (1) { /* Sleep no longer than 1/2s */ queue_wait_w_tmo(&q, &ev, HZ/2);
if (ev.id == SYS_USB_CONNECTED) { /* Switch to verbose mode if not in it so that the status updates * are shown */ verbose = true; /* Got the message - wait for disconnect */ printf("Bootloader USB mode");
usb = USB_HANDLED; usb_acknowledge(SYS_USB_CONNECTED_ACK, ev.data);#if defined(SANSA_E200) && defined(HAVE_BOOTLOADER_USB_MODE) /* E200 misses unplug randomly probably fine for other targets too but needs tested */ while (usb_wait_for_disconnect_w_tmo(&q, HZ * 5) > 0) { /* timeout */ if (!usb_plugged()) break; }#else usb_wait_for_disconnect(&q);#endif break; }
if (connect_timeout != TIMEOUT_BLOCK && TIME_AFTER(current_tick, end_tick)) { /* Timed out waiting for the connect - will happen when connected * to a charger instead of a host port and the charging pin is * the same as the USB pin */ printf("USB: Timed out"); break; }
if (!usb_plugged()) break; /* Cable pulled */ }
usb_close(); queue_delete(&q);
return usb;}#elif (defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)) && \ !defined(USE_ROCKBOX_USB)/* Return USB_INSERTED if cable present */static int handle_usb(int connect_timeout){ int usb_retry = 0; int usb = USB_EXTRACTED;
usb_init(); while (usb_drv_powered() && usb_retry < 5 && usb != USB_INSERTED) { usb_retry++; sleep(HZ/4); usb = usb_detect(); }
if (usb != USB_INSERTED) usb = USB_EXTRACTED;
return usb; (void)connect_timeout;}#else/* Ignore cable state */static int handle_usb(int connect_timeout){ return USB_EXTRACTED; (void)connect_timeout;}#endif /* HAVE_BOOTLOADER_USB_MODE */
void* main(void){ int i; int btn; int rc; int num_partitions; struct partinfo pinfo;#if !(CONFIG_STORAGE & STORAGE_SD) char buf[256]; unsigned short* identify_info;#endif int usb = USB_EXTRACTED;
system_init();#if defined(SANSA_E200) && defined(HAVE_BOOTLOADER_USB_MODE) core_allocator_init();#endif kernel_init();
#ifdef HAVE_BOOTLOADER_USB_MODE /* loader must service interrupts */ enable_interrupt(IRQ_FIQ_STATUS);#endif
lcd_init();
font_init(); show_logo();
adc_init();#ifdef HAVE_BOOTLOADER_USB_MODE button_init_device();#else button_init();#endif#if defined(SANSA_E200) || defined(PHILIPS_SA9200) i2c_init(); backlight_hw_on();#endif
if (button_hold()) { verbose = true; lcd_clear_display(); printf("Hold switch on"); printf("Shutting down..."); sleep(HZ); power_off(); }
btn = button_read_device();
/* Enable bootloader messages if any button is pressed */#ifdef HAVE_BOOTLOADER_USB_MODE lcd_clear_display(); if (btn) verbose = true;#else if (btn) { lcd_clear_display(); verbose = true; }#endif
lcd_setfont(FONT_SYSFIXED);
printf("Rockbox boot loader"); printf("Version: %s", rbversion); printf(MODEL_NAME);
i=storage_init();#if !(CONFIG_STORAGE & STORAGE_SD) if (i==0) { identify_info=ata_get_identify(); /* Show model */ for (i=0; i < 20; i++) { ((unsigned short*)buf)[i]=htobe16(identify_info[i+27]); } buf[40]=0; for (i=39; i && buf[i]==' '; i--) { buf[i]=0; } printf(buf); } else { error(EATA, i, true); }#endif
filesystem_init(); num_partitions = disk_mount_all(); if (num_partitions<=0) { error(EDISK,num_partitions, true); }
/* Just list the first 2 partitions since we don't have any devices yet that have more than that */ for(i=0; i<NUM_PARTITIONS; i++) { disk_partinfo(i, &pinfo); printf("Partition %d: 0x%02x %ld MB", i, pinfo.type, pinfo.size / 2048); }
/* Now that storage is initialized, check for USB connection */ if ((btn & BOOTLOADER_BOOT_OF) == 0) { usb_pin_init(); usb = handle_usb(HZ*2); if (usb == USB_INSERTED) btn |= BOOTLOADER_BOOT_OF; }
/* Try loading Rockbox, if that fails, fall back to the OF */ if((btn & BOOTLOADER_BOOT_OF) == 0) { printf("Loading Rockbox...");
rc = load_mi4(loadbuffer, BOOTFILE, MAX_LOADSIZE); if (rc <= EFILE_EMPTY) { bool old_verbose = verbose; verbose = true; printf("Can't load " BOOTFILE ": "); printf(loader_strerror(rc)); verbose = old_verbose; btn |= BOOTLOADER_BOOT_OF; sleep(5*HZ); } else goto main_exit; }
if(btn & BOOTLOADER_BOOT_OF) { /* Load original mi4 firmware in to a memory buffer called loadbuffer. The rest of the loading is done in crt0.S. 1) First try reading from the hidden partition (on Sansa only). 2) Next try a decrypted mi4 file in /System/OF.mi4 3) Finally, try a raw firmware binary in /System/OF.bin. It should be a mi4 firmware decrypted and header stripped using mi4code. */ printf("Loading original firmware...");
#if (CONFIG_STORAGE & STORAGE_SD) /* First try a (hidden) firmware partition */ printf("Trying firmware partition"); disk_partinfo(1, &pinfo); if(pinfo.type == PARTITION_TYPE_OS2_HIDDEN_C_DRIVE) { rc = load_mi4_part(loadbuffer, &pinfo, MAX_LOADSIZE, usb == USB_INSERTED); if (rc <= EFILE_EMPTY) { printf("Can't load from partition"); printf(loader_strerror(rc)); } else { goto main_exit; } } else { printf("No hidden partition found."); }#endif
#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330) || defined(PHILIPS_SA9200) printf("Trying /System/OF.ebn"); rc=load_mi4(loadbuffer, "/System/OF.ebn", MAX_LOADSIZE); if (rc <= EFILE_EMPTY) { printf("Can't load /System/OF.ebn"); printf(loader_strerror(rc)); } else { goto main_exit; }#endif
printf("Trying /System/OF.mi4"); rc=load_mi4(loadbuffer, "/System/OF.mi4", MAX_LOADSIZE); if (rc <= EFILE_EMPTY) { printf("Can't load /System/OF.mi4"); printf(loader_strerror(rc)); } else {#if defined(SAMSUNG_YH925) lcd_reset();#endif goto main_exit; }
printf("Trying /System/OF.bin"); rc=load_raw_firmware(loadbuffer, "/System/OF.bin", MAX_LOADSIZE); if (rc <= EFILE_EMPTY) { printf("Can't load /System/OF.bin"); printf(loader_strerror(rc)); } else {#if defined(SAMSUNG_YH925) lcd_reset();#endif goto main_exit; }
error(0, 0, true); }
main_exit:#ifdef HAVE_BOOTLOADER_USB_MODE storage_close(); system_prepare_fw_start();#endif
return (void*)loadbuffer;}