/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2017 Marcin Bukat * Copyright (C) 2016 Amaury Pouly * * 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 #include #include #include #include #include #include #include "system.h" #include "mv.h" #include "font.h" #include "power.h" #include "button.h" #include "backlight-target.h" #include "lcd.h" #include "panic.h" #include "filesystem-hosted.h" /* forward-declare */ bool os_file_exists(const char *ospath); /* to make thread-internal.h happy */ uintptr_t *stackbegin; uintptr_t *stackend; static void sig_handler(int sig, siginfo_t *siginfo, void *context) { /* safe guard variable - we call backtrace() only on first * UIE call. This prevent endless loop if backtrace() touches * memory regions which cause abort */ static bool triggered = false; lcd_set_backdrop(NULL); lcd_set_drawmode(DRMODE_SOLID); lcd_set_foreground(LCD_BLACK); lcd_set_background(LCD_WHITE); unsigned line = 0; lcd_setfont(FONT_SYSFIXED); lcd_set_viewport(NULL); lcd_clear_display(); /* get context info */ ucontext_t *uc = (ucontext_t *)context; unsigned long pc = uc->uc_mcontext.pc; unsigned long sp = uc->uc_mcontext.gregs[29]; lcd_putsf(0, line++, "%s at %08x", strsignal(sig), pc); if(sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS || sig == SIGTRAP) lcd_putsf(0, line++, "address 0x%08x", siginfo->si_addr); if(!triggered) { triggered = true; rb_backtrace(pc, sp, &line); } #ifdef ROCKBOX_HAS_LOGF lcd_putsf(0, line++, "logf:"); logf_panic_dump(&line); #endif lcd_update(); system_exception_wait(); /* If this returns, try to reboot */ backlight_hw_off(); system_reboot(); while (1); /* halt */ } static int axp_hw; void power_off(void) { backlight_hw_off(); axp_hw = open("/dev/axp173", O_RDWR | O_CLOEXEC); if(axp_hw < 0) panicf("Cannot open '/dev/axp173'"); if(ioctl(axp_hw, 0x20003323, 0) < 0) { panicf("Call AXP173_SHUTDOWN fail"); } close(axp_hw); } void system_init(void) { int *s; /* fake stack, to make thread-internal.h happy */ stackbegin = stackend = (uintptr_t*)&s; /* catch some signals for easier debugging */ struct sigaction sa; sigfillset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = &sig_handler; sigaction(SIGILL, &sa, NULL); sigaction(SIGABRT, &sa, NULL); sigaction(SIGFPE, &sa, NULL); sigaction(SIGSEGV, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGBUS, &sa, NULL); sigaction(SIGTERM, &sa, NULL); } void system_reboot(void) { backlight_hw_off(); system("/sbin/reboot"); while (1); /* halt */ } void system_exception_wait(void) { backlight_hw_on(); backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING); /* wait until button press and release */ while(button_read_device() != 0) {} while(button_read_device() == 0) {} while(button_read_device() != 0) {} while(button_read_device() == 0) {} } bool hostfs_removable(IF_MD_NONVOID(int drive)) { #ifdef HAVE_MULTIDRIVE if (drive > 0) /* Active LOW */ return true; else #endif #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN return true; #else return false; /* internal: always present */ #endif } bool hostfs_present(IF_MD_NONVOID(int drive)) { #ifdef HAVE_MULTIDRIVE if (drive > 0) /* Active LOW */ #if defined(MULTIDRIVE_DEV) return os_file_exists(MULTIDRIVE_DEV); #else return true; #endif else #endif #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN return os_file_exists(ROOTDRIVE_DEV); #else return true; /* internal: always present */ #endif } #ifdef HAVE_MULTIDRIVE int volume_drive(int drive) { return drive; } #endif /* HAVE_MULTIDRIVE */ #ifdef CONFIG_STORAGE_MULTI int hostfs_driver_type(int drive) { #if (CONFIG_STORAGE & STORAGE_USB) return drive > 0 ? STORAGE_USB_NUM : STORAGE_HOSTFS_NUM; #else return drive > 0 ? STORAGE_SD_NUM : STORAGE_HOSTFS_NUM; #endif } #endif /* CONFIG_STORAGE_MULTI */ int hostfs_init(void) { return 0; } int hostfs_flush(void) { sync(); return 0; } #ifdef HAVE_HOTSWAP bool volume_removable(int volume) { /* don't support more than one partition yet, so volume == drive */ return hostfs_removable(volume); } bool volume_present(int volume) { /* don't support more than one partition yet, so volume == drive */ return hostfs_present(volume); } #endif