Rev 936 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
////// Copyright 2010 TheSeven////// This file is part of emCORE.//// emCORE 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.//// emCORE is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.// See the GNU General Public License for more details.//// You should have received a copy of the GNU General Public License along// with emCORE. If not, see <http://www.gnu.org/licenses/>.////#include "global.h"#include "thread.h"#include "console.h"#include "power.h"#include "interrupt.h"#include "ucl.h"#include "util.h"#include "execimage.h"#include "targetinit.h"#include "malloc.h"#ifdef HAVE_LCD#include "lcd.h"#include "lcdconsole.h"#endif#ifdef HAVE_I2C#include "i2c.h"#endif#ifdef HAVE_USB#include "usb/usbglue.h"#endif#ifdef HAVE_STORAGE#include "storage.h"#include "disk.h"#include "file.h"#endif#ifdef HAVE_BOOTFLASH#include "bootflash.h"#endif#ifdef HAVE_BACKLIGHT#include "backlight.h"#endif#ifndef BATTERY_BOOT_LOCKOUT_THRESHOLD#define BATTERY_BOOT_LOCKOUT_THRESHOLD 0#endifextern int _poolstart; // Not an int at all, but gcc complains about void types being// used here, and we only need the address, so just make it happy...enum boottype{BOOTTYPE_PIGGYBACKED = 1,BOOTTYPE_BOOTFLASH = 2,BOOTTYPE_FILESYSTEM = 3,BOOTTYPE_FAKESUCCESS = 4};struct bootoption{struct bootoption* success_next;struct bootoption* fail_next;int type;char* source;};struct bootinfo{char signature[8];int version;void* baseaddr;size_t totalsize;struct bootoption* options;};struct initbss{struct scheduler_thread initthread;uint32_t initstack[0x400];#ifdef HAVE_STORAGEstruct scheduler_thread storagethread;uint32_t storagestack[0x400];struct wakeup storagewakeup;#endif};static const char welcomestring[] INITCONST_ATTR = "emCORE v" VERSION " r" VERSION_SVN "\n\n";static const char initthreadname[] INITCONST_ATTR = "Initialization thread";static const char unknownboottypestr[] INITCONST_ATTR = "Skipping boot option with unknown type %d\n";static const char nobootoptionsstr[] INITCONST_ATTR = "No usable boot options, waiting for USB commands\n\n";#ifdef HAVE_STORAGEstatic const char storagethreadname[] INITCONST_ATTR = "Storage init thread";#endifstruct bootinfo bootinfo INITTAIL_ATTR ={.signature = "emCOboot",.version = 1,.baseaddr = &bootinfo,.totalsize = sizeof(struct bootinfo),.options = NULL};#ifdef HAVE_STORAGEvoid storageinitthread(void* arg0, void* arg1, void* arg2, void* arg3) INITCODE_ATTR;void storageinitthread(void* arg0, void* arg1, void* arg2, void* arg3){struct initbss* ib = (struct initbss*)arg0;DEBUGF("Battery state: %d, %d mV, %d mAh", read_battery_state(0),read_battery_voltage(0), read_battery_mwh_current(0));switch (read_battery_state(0)){case BATTERY_STATE_NONPRESENT:cputs(CONSOLE_BOOT, "No battery connected.\n");break;case BATTERY_STATE_IDLE:case BATTERY_STATE_CHARGING:case BATTERY_STATE_DISCHARGING:if (read_battery_mwh_current(0) <= BATTERY_BOOT_LOCKOUT_THRESHOLD){backlight_set_brightness(50);cputs(CONSOLE_BOOT, "The battery is discharged.\n""Please connect to a power supply\n""and wait a few minutes.\n");while (read_battery_mwh_current(0) <= BATTERY_BOOT_LOCKOUT_THRESHOLD){DEBUGF("Battery state: %d, %d mV, %d mAh", read_battery_state(0),read_battery_voltage(0), read_battery_mwh_current(0));sleep(10000000);if (read_battery_state(0) != BATTERY_STATE_CHARGING){shutdown(true);power_off();}}backlight_set_brightness(100);}}DEBUGF("Initializing storage drivers...");int rc = storage_init();if (IS_ERR(rc)){DEBUGF("Storage init error: %08X\n", rc);cprintf(CONSOLE_BOOT, "Storage init error: %08X\n", rc);}DEBUGF("Initializing storage subsystem...");disk_init_subsystem();DEBUGF("Mounting partitions...");rc = disk_mount_all();if (IS_ERR(rc)){DEBUGF("FS mount error: %08X\n", rc);cprintf(CONSOLE_BOOT, "FS mount error: %08X\n", rc);}DEBUGF("Storage init finished.");wakeup_signal(&(ib->storagewakeup));}#endifvoid initthread(void* arg0, void* arg1, void* arg2, void* arg3) INITCODE_ATTR;void initthread(void* arg0, void* arg1, void* arg2, void* arg3){struct initbss* ib = (struct initbss*)arg0;#ifdef HAVE_I2Ci2c_init();#endifpower_init();cputs(CONSOLE_BOOT, welcomestring);#ifdef HAVE_STORAGEwakeup_init(&(ib->storagewakeup));thread_create(&(ib->storagethread), storagethreadname, storageinitthread, ib->storagestack,sizeof(ib->storagestack), USER_THREAD, 127, true, ib, NULL, NULL, NULL);#endif#ifdef HAVE_USBusbmanager_init();#endif#ifdef HAVE_BACKLIGHTbacklight_init();#endif#ifdef HAVE_BUTTONbutton_init();#endif#ifdef HAVE_TARGETINIT_LATEtargetinit_late();#endif#ifdef HAVE_STORAGEwhile (true){if (wakeup_wait(&(ib->storagewakeup), 100000) == THREAD_OK) break;enum thread_state state = thread_get_state(&(ib->storagethread));if (state == THREAD_DEFUNCT_ACK){if (wakeup_wait(&(ib->storagewakeup), 0) == THREAD_OK) break;thread_terminate(&(ib->storagethread));break;}}#endif#ifdef HAVE_TARGETINIT_VERYLATEtargetinit_verylate();#endifDEBUGF("Finished initialisation sequence");struct bootoption* option = bootinfo.options;bool success = false;while (option){success = false;switch (option->type){case BOOTTYPE_PIGGYBACKED:success = execimage(option->source, true, 0, NULL) != NULL;break;#ifdef HAVE_BOOTFLASHcase BOOTTYPE_BOOTFLASH:{int size = bootflash_filesize(option->source);if (size <= 0) break;void* buffer = memalign(0x10, size);if (!buffer) break;if (bootflash_read(option->source, buffer, 0, size) != size){free(buffer);break;}success = execimage(buffer, false, 0, NULL) != NULL;break;}#endif#ifdef HAVE_STORAGEcase BOOTTYPE_FILESYSTEM:{int fd = file_open(option->source, O_RDONLY);if (fd <= 0) break;int size = filesize(fd);if (size <= 0){close(fd);break;}void* buffer = memalign(0x10, size);if (!buffer){close(fd);break;}if (read(fd, buffer, size) != size){free(buffer);close(fd);break;}close(fd);success = execimage(buffer, false, 0, NULL) != NULL;break;}#endifcase BOOTTYPE_FAKESUCCESS:success = true;break;default:cprintf(CONSOLE_BOOT, unknownboottypestr, option->type);}if (success) option = option->success_next;else option = option->fail_next;}if (!success) cputs(CONSOLE_BOOT, nobootoptionsstr);}void init() INITCODE_ATTR;void init(){#ifdef HAVE_TARGETINIT_VERYEARLYtargetinit_veryearly();#endifscheduler_init();console_init();#ifdef HAVE_LCDlcd_init();lcdconsole_init();#endif#ifdef HAVE_TARGETINIT_EARLYtargetinit_early();#endifmalloc_init();size_t size = (size_t)(&bootinfo) - (size_t)(&_poolstart) + bootinfo.totalsize;void* bootalloc = malloc(size);size -= (size_t)(bootalloc) - (size_t)(&_poolstart);realloc(bootalloc, size);struct initbss* ib = (struct initbss*)malloc(sizeof(struct initbss));reownalloc(ib, OWNER_TYPE(OWNER_THREAD, &(ib->initthread)));reownalloc(bootalloc, OWNER_TYPE(OWNER_THREAD, &(ib->initthread)));thread_create(&(ib->initthread), initthreadname, initthread, ib->initstack,sizeof(ib->initstack), OS_THREAD, 127, true, ib, NULL, NULL, NULL);timer_init();interrupt_init();}